[C#] “가상이 아닌 (VB에서 재정의 할 수없는) 멤버에서 유효하지 않은 설정 …”메시지와 함께 예외가 발생하는 이유는 무엇입니까?

부울 유형을 반환하는 비가 상 메소드를 조롱 해야하는 단위 테스트가 있습니다.

public class XmlCupboardAccess
{
    public bool IsDataEntityInXmlCupboard(string dataId,
                                          out string nameInCupboard,
                                          out string refTypeInCupboard,
                                          string nameTemplate = null)
    {
        return IsDataEntityInXmlCupboard(_theDb, dataId, out nameInCupboard, out refTypeInCupboard, nameTemplate);
    }
}

그래서 XmlCupboardAccess클래스 의 모의 객체가 있고 아래 표시된 것처럼 테스트 케이스 에서이 메소드에 대한 모의를 설정하려고합니다.

[TestMethod]
Public void Test()
{
    private string temp1;
    private string temp2;
    private Mock<XmlCupboardAccess> _xmlCupboardAccess = new Mock<XmlCupboardAccess>();
    _xmlCupboardAccess.Setup(x => x.IsDataEntityInXmlCupboard(It.IsAny<string>(), out temp1, out temp2, It.IsAny<string>())).Returns(false);
    //exception is thrown by this line of code
}

그러나이 줄은 예외를 던졌습니다.

Invalid setup on a non-virtual (overridable in VB) member:
x => x.IsDataEntityInXmlCupboard(It.IsAny<String>(), .temp1, .temp2,
It.IsAny<String>())

이 예외를 해결하는 방법에 대한 제안이 있으십니까?



답변

Moq는 비가 상 메서드와 봉인 클래스를 조롱 할 수 없습니다. 모의 객체를 사용하여 테스트를 실행하는 동안 MOQ는 실제로 “XmlCupboardAccess”에서 상속하고 “SetUp”메소드에서 설정 한 동작을 무시하는 메모리 내 프록시 유형을 만듭니다. C #에서 알 수 있듯이 Java에서는 그렇지 않은 가상으로 표시된 경우에만 무언가를 무시할 수 있습니다. Java는 모든 비 정적 메소드가 기본적으로 가상 인 것으로 가정합니다.

고려해야 할 또 다른 사항은 “CupboardAccess”에 대한 인터페이스를 도입하고 대신 인터페이스를 조롱하는 것입니다. 코드를 분리하고 장기적으로 이익을 얻는 데 도움이됩니다.

: 마지막으로, 같은 프레임 워크가 TypeMockJustMock 가상이 아닌 방법을 조롱 할 수 따라서 IL 직접 작업합니다. 그러나 둘 다 상용 제품입니다.


답변

나와 같은 문제가있는 사람을 돕기 위해 실수로 인터페이스 대신 구현 유형을 잘못 입력했습니다.

var mockFileBrowser = new Mock<FileBrowser>();

대신에

var mockFileBrowser = new Mock<IFileBrowser>();


답변

내가 조롱하려는 부동산이 가상이어야하는 이유를 참조하십시오
.

Moq가 호출을 가로 채고 호출에 넣은 사용자 지정 값을 반환하는 데 사용되는 프록시 클래스를 만들 때 래퍼 인터페이스를 작성하거나 속성을 가상 / 추상으로 표시해야 할 수 있습니다 .Returns(x).


답변

구체적인 클래스를 조롱하는 대신 해당 클래스 인터페이스를 조롱해야합니다. XmlCupboardAccess 클래스에서 인터페이스 추출

public interface IXmlCupboardAccess
{
    bool IsDataEntityInXmlCupboard(string dataId, out string nameInCupboard, out string refTypeInCupboard, string nameTemplate = null);
}

그리고 대신

private Mock<XmlCupboardAccess> _xmlCupboardAccess = new Mock<XmlCupboardAccess>();

로 변경

private Mock<IXmlCupboardAccess> _xmlCupboardAccess = new Mock<IXmlCupboardAccess>();


답변

인터페이스의 확장 메소드가 호출되는지 확인하는 경우에도이 오류가 발생합니다.

예를 들어 조롱하는 경우 :

var mockValidator = new Mock<IValidator<Foo>>();
mockValidator
  .Verify(validator => validator.ValidateAndThrow(foo, null));

인터페이스 .ValidateAndThrow()의 확장 이기 때문에 동일한 예외 가 발생 합니다 IValidator<T>.

public static void ValidateAndThrow<T>(this IValidator<T> validator, T instance, string ruleSet = null)...


답변

암호:

private static void RegisterServices(IKernel kernel)
{
    Mock<IProductRepository> mock=new Mock<IProductRepository>();
    mock.Setup(x => x.Products).Returns(new List<Product>
    {
        new Product {Name = "Football", Price = 23},
        new Product {Name = "Surf board", Price = 179},
        new Product {Name = "Running shose", Price = 95}
    });

    kernel.Bind<IProductRepository>().ToConstant(mock.Object);
}        

그러나 예외를 참조하십시오.


답변