moq从测试类中获取嵌套结构

moq getting nested struct from the testing class
2021-02-23
  •  译文(汉语)
  •  原文(英语)

我正在为以下课程旧版课编写单元测试

Class myLegacyClassPresenter
{
  private MethodA(){}
  private propertyA {get; set;}
  private MethodB(YearValue value){}

 //some more properties & method goes here

 private struct YearValue
 {
    public static int One { get { return 365; } }
    public static int Two { get { return 730; } }
 } 
}

这是我的单元测试.

public void mytest()
{
 //some initializations
 var view = myLegacyView();
 var service = new Mock<ILegacyService>();
 var presenter = new myLegacyClassPresenter(view, service);
 var privateObject = new PrivateObject(presenter);

 //I can access all private methods and properties as follows
 privateObject.invoke("MethodA");
 privateObject.GetProperty("propertyA")

// But How can I get the the Struct Year value to pass to MethodB
privateObject.Invoke("MethodB", new object[]{YearValue.One}); //Compile Error for YearValue 

//I can't change in the class, One way is to define the same struct locally, Is there any other approach we can have to achieve the same result.
}
速聊1:
YearValue参数MethodB吗?如果是这样,则无论您的单元测试如何,代码都不会编译(错误CS0050).
速聊2:
感谢您指出这一点,只需对其进行更新.
速聊4:
我同意@RyanGates,但目前我只是在更新旧的单元测试,该测试使用的是使用折旧方法访问私有方法myLegacyClassPresenter_PrivateAccessor' to PrivateObject的方法.
速聊5:
它可能是一个拼写错误,但是MethodB采用YearValue,但是您试图通过int(YearValue.One)来调用它.我在下面有一个答案,该答案显示了如何传递YearValue.如果您需要传递int YearValue.In,则可以使用反射从答案中获得的类型中获取值.
解决过程1

经典示例显示了如何无法对特定组件进行单元测试,如何对组件进行重新测试!

这是任何模拟框架强制您执行的工作-编写解耦的代码.

几件事情:

  1. 应该认真考虑测试私有方法.在测试私有方法和属性时,破坏封装.

  2. 在您的示例中,myLegacyClassPresenter该类与该YearValue结构紧密结合.您可以使用依赖注入将其解耦.

速聊1:
正如我所提到的,名字暗示myLegacyClassPresenter我不能更改.
解决过程2

如果要创建该结构的实例,则可以使用以下内容

var theType = Type.GetType("MyNamespace.myLegacyClassPresenter+YearValue");
var parameter = Activator.CreateInstance(theType);

privateobject.Invoke("MethodB", new object[]{parameter});

如果您需要传递YearValue.One,则可以使用theType.GetMember()获取值.

I am writing Unit tests for the following class legacy class

Class myLegacyClassPresenter
{
  private MethodA(){}
  private propertyA {get; set;}
  private MethodB(YearValue value){}

 //some more properties & method goes here

 private struct YearValue
 {
    public static int One { get { return 365; } }
    public static int Two { get { return 730; } }
 } 
}

Here is my unit test.

public void mytest()
{
 //some initializations
 var view = myLegacyView();
 var service = new Mock<ILegacyService>();
 var presenter = new myLegacyClassPresenter(view, service);
 var privateObject = new PrivateObject(presenter);

 //I can access all private methods and properties as follows
 privateObject.invoke("MethodA");
 privateObject.GetProperty("propertyA")

// But How can I get the the Struct Year value to pass to MethodB
privateObject.Invoke("MethodB", new object[]{YearValue.One}); //Compile Error for YearValue 

//I can't change in the class, One way is to define the same struct locally, Is there any other approach we can have to achieve the same result.
}
Talk1:
Is YearValue a parameter to MethodB? If so, your code won't compile regardless of your unit tests (it's error CS0050).
Talk2:
Thanks for pointing that out, Just updated it.
Talk4:
I agree with @RyanGates, but at the moment I am just updating the old unit tests which was using the depreciated method of accessing private methods myLegacyClassPresenter_PrivateAccessor' to PrivateObject`
Talk5:
It may be a typo but the MethodB take a YearValue but you are trying to invoke it passing in a int (YearValue.One). I have an answer below that shows how to pass in YearValue. If you need to pass in the int YearValue.One you can use reflection to get the value from the type obtained in the answer
Solutions1

Classic example which shows how if you cannot unit test a particular component, REFACTOR the component!

This is where is love what any mocking framework enforces you to do - write decoupled code.

Couple of things:

  1. Testing private methods should be seriously reconsidered. You break encapsulation the moment you test private methods and properties.

  2. In your example, the myLegacyClassPresenter class is very tightly coupled with the YearValue struct. You could decouple it using dependency injection.

Talk1:
As I mentioned and name suggests that myLegacyClassPresenter cannot be changed in my case.
Solutions2

If you want to create an instance of the struct you can use something like the following

var theType = Type.GetType("MyNamespace.myLegacyClassPresenter+YearValue");
var parameter = Activator.CreateInstance(theType);

privateobject.Invoke("MethodB", new object[]{parameter});

If you need to pass in YearValue.One, then theType.GetMember() can be used to get the value.

转载于:https://stackoverflow.com/questions/23732996/moq-getting-nested-struct-from-the-testing-class

本人是.net程序员,因为英语不行,使用工具翻译,希望对有需要的人有所帮助
如果本文质量不好,还请谅解,毕竟这些操作还是比较费时的,英语较好的可以看原文

留言回复
我们只提供高质量资源,素材,源码,坚持 下了就能用 原则,让客户花了钱觉得值
上班时间 : 周一至周五9:00-17:30 期待您的加入