单元测试与模拟对象

huangapple go评论53阅读模式
英文:

Unit test with Mock Object

问题

public class Product
{
    public int Sum(int a, int b) => a + b;
}

[TestMethod]
public void SumTest()
{
    var moc = new Mock<Product>();
    moc.Setup(m => m.Sum(1, 1)).Returns(3);
}
如何在类中进行模拟(而不是接口或虚函数)以设置(...)。返回(...)?
在这种情况下,我无法将对象或类添加到接口或虚拟函数。

否则,我无法使用模拟来创建虚假数据。如何创建虚假数据?**但不能更改类和方法的类型**。请给我一些建议。
感谢大家
英文:
public class Product
{
    public int Sum(int a, int b) =&gt; a +b;
}

[TestMethod]
public void SumTest()
{
    var moc = new Mock&lt;Product&gt;();
    moc.Setup(m =&gt; m.Sum(1, 1)).Returns(3);
}

How to Mock from class(not interface or not virtual function) can Setup(...).Returns(...)?
I can not add the object or class to the interface or virtual in this case.

otherwise, I can not make fake date with Mock. How can I make fake data? but can not change type class and method. Please give me some advice.
Thanks all

答案1

得分: 2

不能使用Moq来改变类似这样的非虚拟方法的行为。

Moq的工作方式类似于继承被模拟的类型(类或接口),然后覆盖相关的成员(方法)。但在这种情况下是不可能的。

要使用Moq,被模拟的类型必须是接口或非静态的非密封类,成员必须是abstractvirtual(包括未sealed overrideoverride)。还有访问级别的限制,但在您的情况下,既类又方法都是public,所以这不是问题。

英文:

You cannot use Moq to alter the behavior of a nonvirtual method on a class like this.

The way Moq works is similar to inheriting from the type (class or interface) mocked, and then overriding the member (method) in question. That is not possible in this case.

To use Moq, the mocked type must be either an interface or a nonstatic nonsealed class, and the member must be either abstract or virtual (including override that is not sealed override). There are also limitation on the access levels, but that is not a problem in your case where both the class and the method are public.

答案2

得分: 1

一如既往,另一层抽象可以在这里有所帮助:

public interface IProduct
{
int Sum(int a, int b);
}

public class ProductWrapper: IProduct
{
readonly Product product;
ProductWrapper(Product product) => this.product = product;
public int Sum(int a, int b) => product.Sum(a, b);
}

拥有这些内容后,您可以开始依赖于抽象(`IProduct`)而不是具体实现(`Product`或`ProductWrapper`),这使您能够模拟依赖项。

//准备
var productMock = new Mock();
productMock.Setup(m => m.Sum(1, 1)).Returns(3);

var sut = new SUT(productMock.Object);

//操作
//...


<details>
<summary>英文:</summary>

As always another layer of abstraction can help here :) 

public interface IProduct
{
int Sum(int a, int b);
}

public class ProductWrapper: IProduct
{
readonly Product product;
ProductWrapper(Product product) => this.product = product;
public int Sum(int a, int b) => product.Sum(a, b);
}

With these in your hand you can start depending on abstraction (`IProduct`) rather than implementation (`Product` or `ProductWrapper`) which allows you mock your dependency.

//Arrange
var productMock = new Mock<IProduct>();
productMock.Setup(m => m.Sum(1, 1)).Returns(3);

var sut = new SUT(productMock.Object);

//Act
//...


</details>



huangapple
  • 本文由 发表于 2023年3月31日 18:14:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75897355.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定