首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >xUnit测试添加模型以列出失败

xUnit测试添加模型以列出失败
EN

Stack Overflow用户
提问于 2014-05-27 13:43:09
回答 1查看 452关注 0票数 0

我正在使用xUnit测试我的项目。我有一个测试,它检查一个user是否添加了一个list of users,如下所示:

代码语言:javascript
复制
private readonly IJsonService _jsonService;
private readonly IUserService _userService;

[Fact]
    public void Add_User_To_User_List()
    {
        //Given
        _userService = new UserService(_jsonService, _guidService);
        _jsonService = Substitute.For<IJsonService>();

        var _fakeUserJsonFile = "Users.json";
        var _fakeNewUser = new User()
        {
            ID = new Guid(),
            FirstName = "Denis",
            LastName = "Menis"
        };

        var _fakeUserList = new List<User>
        {
            new User()
                {
                    ID = new Guid(),
                    FirstName = "Paddy",
                    LastName = "Halle"
                },
            new User()
                {
                    ID = new Guid(),
                    FirstName = "Job",
                    LastName = "Blogs"
                }
        };

        var _fakeUpdatedUserList = new List<User>
        {
            new User()
                {
                    ID = new Guid(),
                    FirstName = "Paddy",
                    LastName = "Halle"
                },
            new User()
                {
                    ID = new Guid(),
                    FirstName = "Job",
                    LastName = "Blogs"
                },
            new User()
                {
                    ID = new Guid(),
                    FirstName = "Denis",
                    LastName = "Menis"
                }
        };

        _jsonService.DeserializeObject<User>(_fakeUserJsonFile).Returns(_fakeUserList);
        _jsonService.SerializeObject(_fakeUserJsonFile, _fakeUpdatedUserList).Returns(true);

        //When
        var result = _userService.AddUser(_fakeNewUser);

        //Then
        Assert.Contains(_fakeNewUser, _fakeUpdatedUserList);
    }

现在,我知道代码可以工作,因为我首先编写了它,但是当我运行测试时,它失败了!下面是我将用户添加到用户列表中的代码:

代码语言:javascript
复制
public bool AddUser(User user)
    {
        var userList = GetUsers();

        user.ID = _guidService.NewGuid();

        userList.Add(user);

        var serializeObject = _jsonService.SerializeObject(_fileName, userList);

        return serializeObject;
    }

GetUser方法:

代码语言:javascript
复制
public List<User> GetUsers()
    {
        return _jsonService.DeserializeObject<User>(_fileName).ToList();
    }

反序列化方法:

代码语言:javascript
复制
private readonly IFileSystem _file;
    private readonly HttpContextBase _httpContext;
    private readonly ILogger _logger;

    public JsonService(IFileSystem file, HttpContextBase httpContext, ILogger logger)
    {
        _file = file;
        _httpContext = httpContext;
        _logger = logger;
    }

    public IEnumerable<T> DeserializeObject<T>(string fileName)
    {
        try
        {
            var relativeFileName = _httpContext.Server.MapPath(fileName);
            var readFile = _file.ReadAllText(relativeFileName);
            var list = JsonConvert.DeserializeObject<List<T>>(readFile);
            return list;
        }
        catch (Exception ex)
        {
            _logger.LogException(ex);
            return null;
        }
    }

FileSystem类:

代码语言:javascript
复制
public class FileSystem : IFileSystem
{
    public void WriteAllText(string path, string contents)
    {
        File.WriteAllText(path, contents);
    }

    public string ReadAllText(string path)
    {
        return File.ReadAllText(path);
    }
}

当我运行我的测试时,来自AddUser方法的AddUser每次都会返回false。

我认为它这样做是因为,尽管它与预期结果相同,但在内存中,它是对相同数据的不同引用。

有人能帮我做这件事吗?我想让它返回相同的参考数据。如果我不太清楚的话,我可以再详细说明一下。谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-27 16:22:35

您完全正确地认为,问题的根源在于_fakeUserList_fakeUpdatedUserList引用了两个完全不同的对象。您已经将_jsonService.SerializeObject配置为在传递对_fakeUpdatedUserList的引用时返回true,但实际上是传递对(修改的) _fakeUserList的引用。

基本上,_fakeUpdatedUserList是完全不必要的。您可以关注_fakeUserList,因为它是提供给SUT的对象(大概是通过DeserializeObject<User>提供的)。

例如:

代码语言:javascript
复制
[Fact]
public void Add_User_To_User_List()
{
    //Given
    _userService = new UserService(_jsonService, _guidService);
    _jsonService = Substitute.For<IJsonService>();

    var _fakeUserJsonFile = "Users.json";
    var _fakeNewUser = new User()
    {
        ID = new Guid(),
        FirstName = "Denis",
        LastName = "Menis"
    };

    var _fakeUserList = new List<User>
    {
        new User()
            {
                ID = new Guid(),
                FirstName = "Paddy",
                LastName = "Halle"
            },
        new User()
            {
                ID = new Guid(),
                FirstName = "Job",
                LastName = "Blogs"
            }
    };

    _jsonService.DeserializeObject<User>(_fakeUserJsonFile).Returns(_fakeUserList);
    _jsonService.SerializeObject(_fakeUserJsonFile, _fakeUserList).Returns(true); // Match the original _fakeUserList, since that is what gets passed in by the implementation

    //When
    var result = _userService.AddUser(_fakeNewUser);

    //Then
    Assert.Contains(_fakeNewUser, _fakeUserList); // Verify that the provided _fakeUserList has been modified
}

顺便提一句:您实际上可以从这个测试中删除很多细节,因为它们与正在测试的功能无关。例如,_fakeUserList最初可以是空的-它不需要包含任何虚拟值。而且您可以使用_fakeNewUser的默认值(例如,不指定FirstName等),因为在这个测试中根本没有引用它们。

编辑:,谢谢您发布附加代码(用于GetUsers等)。这段代码显示您正在调用由ToList()返回的IEnumerable<User>上的DeserializeObject<User>。这就是为什么模拟对象没有像您预期的那样运行:ToList()返回的列表是一个与_fakeUserList完全不同的列表。

此外,在您的测试中,我没有看到_fakeUserJsonFile被注入SUT的任何地方。因此,_fileName in AddUser可能也不是您所期望的。

要解决这个问题,您需要修改设计(例如,不调用ToList),或者修改测试中的预期行为。虽然您可能想考虑前者的可能性,但后者可能更容易一些。

例如:

代码语言:javascript
复制
    // Match any filename (unless you have a way of getting _fakeUserJsonFile into the SUT)
    // Match any list, as long as it contains the new user
    _jsonService.SerializeObject(Arg.Any<string>(), Arg.Is<List<User>>(list => list.Contains(_fakeNewUser))).Returns(true);

    //When
    var result = _userService.AddUser(_fakeNewUser);

    //Then
    Assert.IsTrue(result); // Only returns true if the mock object is invoked as expected

    // There is no way to verify the following assertion, because the test has no way of accessing the "updated" list
    //Assert.Contains(_fakeNewUser, _fakeUserList);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23891113

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档