我无法让Moq模拟在静态方法中创建的对象。 这是我的moq和代码
代码:
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");
}
}
使用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
}
}
我遇到的问题是这一行:
ConfigHelper configUtil = new ConfigHelper(); //NOT BEING MOCKED
我无法让moq模拟对象。
我不希望代码读取配置文件。我希望moq这个ConfigHelper
答案 0 :(得分:1)
你不能包装静态类/方法,但你可以重定向它
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");
}
}
然后在测试中
//...
private Mock<IConfigHelper> configHelperMOCK;
[SetUp]
public void Setup()
{
configHelperMOCK = new Mock<IConfigHelper>();
UtilService.CreatorFunc = () => configHelperMOCK.Object;
}
//...
答案 1 :(得分:0)
你不能模拟静态类。我宁愿建议将IConfigHelper
注入myRealClass
。这是解决依赖关系和使用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;
}
}
答案 2 :(得分:0)
避免将代码耦合到静态类,这在大多数情况下会导致代码难以维护和测试。
关注Explicit Dependencies Principle
方法和类应明确要求(通常通过 方法参数或构造函数参数)任何协作对象 他们需要才能正常运作。
阅读文章。它简短而且信息量很大。
如果你想保留静态类,那么你将静态类包装在抽象之后。
public interface IUtilSvc {
string GetConfigurationValue();
}
public class utilSvcWrapper : IUtilSvc {
public string GetConfigurationValue() {
return utilSvc.GetConfigurationValue(); //Calling static service
}
}
或者另一种选择是,如果可以将依赖类注入到依赖类中,则utlSvc不必是静态的
public class utilSvc : IUtilScv {
private readonly IConfigHelper configUtil;
public utilSvc(IConfigHelper configHelper) {
configUtil = configHelper;
}
public string GetConfigurationValue() {
return configUtil.GetConfiguration("sectionName/sectionElement", "ClinicalSystem");
}
}
将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;
}
}
在这种情况下,您在测试时甚至不需要IConfigHelper
,因为它也被抽象掉了。而且您只需要模拟测试所需的依赖项。
[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);
}
}