如何模拟 Save 方法行为来测试我的存储库?

How to mock a Save method behavior for testing my repository?

我有以下存储库:

public class WorkspaceRepo : IWorkspacesRepo
{
    private readonly ApplicationContext _applicationContext;

    public WorkspaceRepo(ApplicationContext applicationContext)
    {
        _applicationContext = applicationContext;
    }

    public IEnumerable<Workspace> Workspaces => _applicationContext.Workspaces;

    public void Save(Workspace workspace)
    {
        _applicationContext.Workspaces.Add(workspace);
        _applicationContext.SaveChanges();
    }
}

下面的方法来自我的业务逻辑class。我需要测试这个方法:

public Workspace CreateWorkspace(Workspace workspace)
{
    if (string.IsNullOrEmpty(workspace.UserUuid))
    {
        throw new RpcException(new Status(StatusCode.NotFound, "Empty user Uuid"));
    }

    var freSlots =  10 - _workspacesRepo.Workspaces.Count(x => x.UserUuid == workspace.UserUuid);

    if (freSlots <= 0)
    {
        throw new RpcException(new Status(StatusCode.Aborted, "There are no free slots work workspaces"));
    }

    _workspacesRepo.Save(workspace);

    return workspace;
}

业务逻辑很简单。我只能保存 10 Workspace 个对象。下次储蓄一定要给我RpcException。现在我想测试一下。这是测试代码:

[Test]
public void User_Cant_Exceed_Workspaces_Limit()
{
    // organization
    Mock<IWorkspacesRepo> mock = new Mock<IWorkspacesRepo>();
    mock.Setup(m => m.Save(It.IsAny<Workspace>())).Callback( /* what to do here?*/ )    

    var target = new WorkspaceBusinessService(mock.Object, null);

    for (var i = 0; i < 10; i++)
    {
        target.CreateWorkspace(new Workspace
        {
            Name = Guid.NewGuid().ToString(),
            UserUuid = Guid.NewGuid().ToString(),
            WorkspaceId = i + 1
        });
    }

    var redundantWorkspace = new Workspace
    {
        Name = Guid.NewGuid().ToString(),
        UserUuid = Guid.NewGuid().ToString(),
        WorkspaceId = 11
    };

    // action
    // asserts
    var ex = Assert.Throws<RpcException>(() => target.CreateWorkspace(redundantWorkspace));
    Assert.That(ex.Message, Is.EqualTo("Status(StatusCode.Aborted, \"There are no free slots work workspaces\")"));
}

但预期的行为并未发生。我用调试和 CreateWorkspace 方法观看了这个,我总是 10 freeSlots。如何测试这种情况?

根据被测方法中的逻辑,您正在模拟错误的成员。

模拟 Workspaces 属性 以便它在

时表现得像预期的那样
//..

var freSlots = 10 - _workspacesRepo.Workspaces.Count(x => x.UserUuid == workspace.UserUuid);

if (freSlots <= 0) {

//...

被调用。

例如

// Arrange
//need common user id
var userUuid = Guid.NewGuid().ToString();

//create workspaces to satisfy Linq Count(Expression)
var workspaces = Enumerable.Range(0, 10).Select(i => new Workspace {
    Name = Guid.NewGuid().ToString(),
    UserUuid = userUuid, //<-- Note the common user id
    WorkspaceId = i + 1
});

Mock<IWorkspacesRepo> mock = new Mock<IWorkspacesRepo>();

//set up the property to return the list
mock.Setup(_ => _.Workspaces).Returns(workspaces);

var target = new WorkspaceBusinessService(mock.Object, null);

var redundantWorkspace = new Workspace {
    Name = Guid.NewGuid().ToString(),
    UserUuid = userUuid, //<-- Note the common user id
    WorkspaceId = 11
};

// Act
Action act = () => target.CreateWorkspace(redundantWorkspace);

//Assert
var ex = Assert.Throws<RpcException>(act);
Assert.That(ex.Message, Is.EqualTo("Status(StatusCode.Aborted, \"There are no free slots work workspaces\")"));