简体   繁体   English

Moq 静态类中的对象

[英]Moq an object in a static class

I can't get Moq to mock an object that gets created in a static method.我无法让 Moq 模拟在静态方法中创建的对象。 Here is my moq and code这是我的起订量和代码

code:代码:

public interface IConfigHelper
{
    string GetConfiguration(string sectionName, string elementName);
}

public class ConfigHelper : IConfigHelper
{
    public ConfigHelper() { }

    public virtual string GetConfiguration(string sectionName, string elementName)
    {
        string retValue = String.Empty;
        //Does things to get configuration and return a value    
        return retValue;
    }
}

public class myRealClass
{
    public myRealClass(){}
    public string myworkingMethod()
    {
        var retValue = String.Empty;
        retValue = utilSvc.GetConfigurationValue();
        return retValue;
    }
}

public static class utilSvc
{
    public static string GetConfigurationValue()
    {
        ConfigHelper configUtil = new ConfigHelper(); //NOT BEING MOCKED
        return configUtil.GetConfiguration("sectionName/sectionElement", "ClinicalSystem");
    }
}

the Test using Moq使用 Moq 进行测试

[TestFixture(TestName = "Tests")]
public class Tests 
{
    private Mock<IConfigHelper> configHelperMOCK;
    [SetUp]
    public void Setup()
    {
        configHelperMOCK = new Mock<IConfigHelper>();
    }

    [Test]
    public void serviceIsBPManagementForValidSource()
    {
        //Arrange
        string sectionName = "sectionName/sectionElement";
        string clinicalElementName = "ClinicalSystem";
        string clinicalElementValue = "Zedmed";
        configHelperMOCK.Setup(s => s.GetConfiguration(sectionName, clinicalElementName)).Returns(clinicalElementValue);

        //act
        // the call to myRealClass

        //assert
        // test assertions
    }
}

The issue that I am having is with this line:我遇到的问题是这一行:

ConfigHelper configUtil = new ConfigHelper(); //NOT BEING MOCKED

I cannot get the moq to Mock the object.我无法获得 Mock 对象的最小起订量。 I do not want the code to read the config file.我不希望代码读取配置文件。 I wish to moq away this instance of ConfigHelper我希望删除这个ConfigHelper实例

You can't wrap the static class/method but you can redirect it您不能包装静态类/方法,但可以重定向它

public static class UtilSvc
{
     static UtilSvc()
     {
         CreatorFunc = () => new ConfigHelper();
     }

     public static Func<IConfigHelper> CreatorFunc { get; set; }

     public static string GetConfigurationValue()
     {
         var configUtil = CreatorFunc();
         return configUtil.GetConfiguration("sectionName/sectionElement", 
                                            "ClinicalSystem");
     }
}

and then in the test然后在测试中

//...
private Mock<IConfigHelper> configHelperMOCK;

[SetUp]
public void Setup()
{
    configHelperMOCK = new Mock<IConfigHelper>();
    UtilService.CreatorFunc = () => configHelperMOCK.Object;
}
//...

You cannot mock static class.你不能模拟静态类。 I would rather propose to inject that IConfigHelper into the myRealClass .我宁愿建议将该IConfigHelper注入myRealClass That is the usual way how to decouple dependencies and use DI.这是解耦依赖和使用 DI 的常用方法。

public class myRealClass
{
  private IConfigHelper _configHelper;  

  public myRealClass(IConfigHelper configHelper)
  {
     _configHelper = configHelper;
  }

  public string myworkingMethod()
  {
     var retValue = String.Empty;
     retValue = _configHelper.GetConfigurationValue();
     return retValue;
   }
}

Avoid coupling your code to static classes, which in most cases cause you code be to difficult to maintain and test.避免将您的代码耦合到静态类,这在大多数情况下会导致您的代码难以维护和测试。

Follow the Explicit Dependencies Principle遵循显式依赖原则

Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.方法和类应该明确要求(通常通过方法参数或构造函数参数)它们需要的任何协作对象才能正常运行。

Give the article a read.把文章读一读。 It is short and very informative.它很短而且信息量很大。

If you want to keep the static class then you wrap the static class behind an abstraction.如果您想保留静态类,那么您可以将静态类包装在抽象之后。

public interface IUtilSvc {
    string GetConfigurationValue();
}

public class utilSvcWrapper : IUtilSvc {
    public string GetConfigurationValue() {
        return utilSvc.GetConfigurationValue(); //Calling static service
    }
}

Or another option is that utlSvc does not have to be static if can be injected into dependent classes或者另一种选择是如果可以注入依赖类,则 utlSvc 不必是静态的

public class utilSvc : IUtilScv {
    private readonly IConfigHelper configUtil;

    public utilSvc(IConfigHelper configHelper) {
        configUtil = configHelper;
    }

    public string GetConfigurationValue() {
        return configUtil.GetConfiguration("sectionName/sectionElement", "ClinicalSystem");
    }
}

Inject the IUtilScv into the dependent class so that it is no longer dependent on static class.IUtilScv注入到依赖类中,使其不再依赖于静态类。

public class myRealClass {
    private readonly IUtilScv utilSvc;

    //Explicit dependency inject via constructor
    public myRealClass(IUtilScv utilSvc) {
        this.utilSvc = utilSvc;
    }

    public string myworkingMethod() {
        var retValue = utilSvc.GetConfiguration();
        return retValue;
    }
}

In that case you don't even need IConfigHelper when testing as it has also been abstracted away.在这种情况下,您在测试时甚至不需要IConfigHelper ,因为它也已被抽象掉。 And you only need to mock the dependencies needed for the test.并且您只需要模拟测试所需的依赖项。

[TestFixture(TestName = "Tests")]
public class Tests {
    private Mock<IUtilScv> utilScvMOCK;

    [SetUp]
    public void Setup() {
        utilScvMOCK = new Mock<IUtilScv>();
    }

    [Test]
    public void serviceIsBPManagementForValidSource() {
        //Arrange
        var expectedClinicalElementValue = "Zedmed";
        utilScvMOCK
            .Setup(s => s.GetConfiguration())
            .Returns(expectedClinicalElementValue)
            .Verifiable();            

        var sut = new myRealClass(utilScvMOCK.Object);

        //Act
        var actualClinicalElementValue = sut.myworkingMethod();

        //Assert
        configHelperMOCK.Verify();
        Assert.AreEqual(expectedClinicalElementValue, actualClinicalElementValue);
    }
}

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

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