简体   繁体   English

使用受保护的方法和模拟字段对 C# 进行单元测试

[英]Unit testing C# with protected methods and Mocking fields

Below is code from a NuGet package which is used by our main project, MyClass is called via the main project with authentication.下面是我们主项目使用的 NuGet 包中的代码,MyClass 通过主项目调用并进行身份验证。 The method GetMyAppStoreConfig() will only work when calling from the main project via authentication. GetMyAppStoreConfig() 方法仅在通过身份验证从主项目调用时才有效。

  public class MyClass : MyClassBase
    {
        private SomeClass1 someClass1;
        private MyAppStore myAppStore; // Field newly added
        
        public MyClass(params object[] args)
            : base(args)
        {
            this.someClass1 = new SomeClass1();
            this.myAppStore = new MyAppStore(GetMyAppStoreConfig()); // Field newly added
        }

           protected override async Task<SomeValues> Process(
            SomeClass2 someClass2,
            SomeClass3 someClass3,
            SomeClass4 someClass4
           )
        {
          ...
          ...
          ...
  
        }
     
    // Below method uses myAppStore
    // Method newly added
        protected override async Task<SomeValues> ProcessWithAuth(
            SomeClass5 someClass5
           )
        {
          ...
          ...
          ...
  
        }

        private AppStoreConfig GetMyAppStoreConfig(){
        ...
        ...
        }


    }

Earlier the test code for above was.早些时候,上面的测试代码是。

 [TestClass()]
    public class MyClassTests : MyClass 
    {
        

        [TestMethod()]
        public void test1()
        {   
            ...
            ... = this.Process(someClass2,someClass3,someClass4);
            ...
        }
   }

But now it doesn't work as it throws error in GetMyAppStoreConfig().但现在它不起作用,因为它在 GetMyAppStoreConfig() 中引发错误。 Currently I don't need to test ProcessWithAuth(), what changes I should make for the test case to work.目前我不需要测试 ProcessWithAuth(),我应该对测试用例进行哪些更改才能正常工作。

I currently cannot create one more constructor and cannot change the protection level in MyClass.cs .我目前无法再创建一个构造函数,也无法更改 MyClass.cs 中的保护级别。

Process() has some code which I want to run in tests and not simply mock. Process() 有一些我想在测试中运行而不是简单地模拟的代码。

Below code worked for me.下面的代码对我有用。 Needed to make getData virtual and create a no argument constructor in MyAppStore.需要使 getData 虚拟化并在 MyAppStore 中创建无参数构造函数。

    [TestClass()]
    public class MyClassTests 
    {
        private MyClass _myClass;
        private PrivateObject privateObject;

        [TestInitialize()]
        public void init()
        {
            this._myClass = (MyClass)FormatterServices.GetSafeUninitializedObject(typeof(MyClass));
            privateObject = new PrivateObject(this._myClass);
            privateObject.SetField("someClass1;", new SomeClass1());

            var myAppStore  = SetUpMyAppStore();
            
            privateObject.SetField("myAppStore", myAppStore);
        }

        private SetUpMyAppStore()
        {
              var myAppStore = new Mock<MyAppStore>();

              var myData = new MyData();
              myData.val = "1123"
              myAppStore.Setup(x => x.getData("data1")).Returns(Task.FromResult(myData));

              myData = new MyData();
              myData.val = "1124"
              myAppStore.Setup(x => x.getData("data2")).Returns(Task.FromResult(myData));

              return myAppStore.Object;

        }


        

        [TestMethod()]
        public void test1()
        {
            ...
            ... =  (Task<SomeValues>)this.privateObject.Invoke("Process",someClass2,someClass3,someClass4);
            ...
           
        } 


        [TestMethod()]
        public void test2()
        {
            ...
            ... =  (Task<SomeValues>)this.privateObject.Invoke("ProcessWithAuth",someClass5);
            ...
           
        } 
         
    }     ```

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM