问题描述
我关注了这个问题 Using Moq to mock only some methods 但仍然抛出了一个异常。
这是我的主要课程。 Foo
充当装饰器。
public class Foo {
public Bar _b {get; set;}
public Foo(Bar b) {
this._b = b;
}
public bool MyMethod(){
return ComplexMethod(_b.name);
}
public bool ComplexMethod(){
...
}
}
测试类
[TestClass]
public class Foo {
[TestMethod]
public void TestFoo() {
var b = new Bar() {name = "name"};
var mock = new Mock<Foo>(b);
mock.CallBase = true;
mock.Setup(x => x.ComplexMethod()).Returns(true);
var result = mock.Object.MyMethod();
...
}
}
抛出异常:
System.NotSupportedException: '不支持的表达式:x => x.ComplexMethod() 不可覆盖的成员(此处:Foo.ComplexMethod) 不能在设置/验证表达式中使用。'
解决方法
您应该模拟依赖项而不是实际对象。因此,如果您想评估 MyMethod
的 Foo
,那么您应该模拟 Bar
。
为了能够模拟Bar
的{{1}}成员:
- 您应该将其标记为
name
或virtual
(ref) - 或者你应该定义一个接口
让我们看看后一种情况:
abstract
使用此设置,您的单元测试可能如下所示:
public interface IBar
{
string Name { get; }
}
public class Bar: IBar
{
public string Name { get; set; }
}
public class Foo
{
private readonly IBar _b;
public Foo(IBar b) {
this._b = b;
}
...
}
[TestMethod]
public void GivenABar_WhereTheNameIsEmpty_WhenICallMyMethod_ThenItReturnsTrue()
{
//Arrange
var barMock = new Mock<IBar>();
barMock.SetupGet(x => x.Name).Returns("");
//Act
var SUT = new Foo(barMock.Object);
var result = SUT.MyMethod();
//Assert
barMock.VerifyGet(m => m.Name,Times.Once);
Assert.True(result);
}
UPDATE:模拟 SUT 的一种方法
如果您只想模拟 only 的 [TestMethod]
public void GivenABar_WhereTheNameIsNotEmpty_WhenICallMyMethod_ThenItReturnsFalse()
{
//Arrange
var barMock = new Mock<IBar>();
barMock.SetupGet(x => x.Name).Returns("test");
//Act
var SUT = new Foo(barMock.Object);
var result = SUT.MyMethod();
//Assert
barMock.VerifyGet(m => m.Name,Times.Once);
Assert.False(result);
}
的 ComplexMethod
,那么您可以使用 moq 的 Foo
。
As
请注意,此技术仅在 const bool expectedResult = true;
var fooMock = new Mock<Foo>(barInstance).As<IFoo>();
fooMock.Setup(f => f.ComplexMethod()).Returns(expectedResult);
实现 Foo
时才有效,IFoo
也公开了
ComplexMethod