我是Mocking的新手,不确定我是否做对了。我试图使用使用WriteNameToDatabase
方法的函数GetName
,所以我的类设置如下:
我的员工界面:
public interface IEmployee
{
Task<string> GetName();
string WriteNameToDataBase();
}
我的员工班级
public class Employee : IEmployee
{
public Task<string> GetName()
{
throw new NotImplementedException();
}
public string WriteNameToDataBase()
{
var employeeName = GetName();
return $"Wrote {employeeName.Result} to database";
}
我的单元测试班
[Test]
public void WriteToDBShouldWrite()
{
var mockObject = new Mock<IEmployee>();
mockObject.Setup(x => x.GetName()).ReturnsAsync("Frank");
string result = mockObject.Object.WriteNameToDataBase();
Assert.AreEqual("Wrote Frank to database", result);
}
这总是返回我Was Expecting 'Wrote Frank to database
,但实际上为空`,或者是Assert给我的某种含义。我在做什么错了?
谢谢
编辑:更正为使用ReturnsAsync("Frank");
答案 0 :(得分:4)
几个问题,一个是您没有等待异步呼叫:
apply
两次嘲笑结果错误,moq支持异步:
public async Task<string> WriteNameToDataBase()
{
var employeeName = await GetName();
return $"Wrote {employeeName} to database";
}
但是这里的主要问题是您模拟整个对象。这没有测试任何东西。您可能想要更多类似的东西:
mockObject.Setup(x => x.GetName()).ReturnsAsync("Frank");
您的仓库现在是由该界面表示的单独的东西
public class Employee : IEmployee
{
private readonly INameRepo _repo;
public Employee(INameRepo repo)
{
//this is dependancy injection
_repo = repo;
}
public async Task<string> WriteNameToDataBase()
{
var employeeName = await _repo.GetName();
return $"Wrote {employeeName.Result} to database";
}
}
然后您的测试如下:
public interface INameRepo
{
Task<string> GetName();
}
如果您只想验证是否调用了[Test]
//note this is also async now
public async Task WriteToDBShouldWrite()
{
//mock the dependencies
var mockObject = new Mock<INameRepo>();
mockObject.Setup(x => x.GetName()).ReturnsAsync("Frank");
//test the actual object
Employee emp = new Employee(mockObject.Object);
string result = await emp.WriteToDBShouldWrite();
Assert.AreEqual("Wrote Frank to database", result);
}
,则应使用GetName
而不是返回任意值:
Verify
答案 1 :(得分:1)
请注意,您是基于接口IEmployee
而不是类Employee
创建Mock对象,因此根本就没有测试Employee
类,因此您无法期望Employee
类中要运行的任何代码。
您需要考虑一下您的测试实际上试图做什么,以及什么构成项目中的“单元”。
您可以创建一个包含INameGetter
方法的新接口GetName
(或对您的项目有意义的名称)。然后,您可以将此新接口作为雇员类中的依赖项,并在测试中对其进行模拟。像这样:
public interface IEmployee
{
Task<string> WriteNameToDataBase();
}
public interface INameGetter
{
Task<string> GetName();
}
public class Employee : IEmployee
{
private INameGetter nameGetter;
public Employee(INameGetter n)
{
nameGetter = n;
}
public Task<string> WriteNameToDataBase()
{
var employeeName = await nameGetter.GetName();
return $"Wrote {employeeName} to database";
}
}
您的测试方法
[Test]
public void WriteToDBShouldWrite()
{
var mockObject = new Mock<INameGetter>();
mockObject.Setup(x => x.GetName()).Returns(Task.FromResult("Frank"));
string result = new Employee(mockObject.Object).WriteNameToDataBase();
Assert.AreEqual("Wrote Frank to database", result);
}
N.B您还需要研究异步/等待以使用返回Task
的方法。编辑:我现在在这里修复了它,但实际上您不想使用Task.Result
。