web-dev-qa-db-ja.com

モックを使用したNunitテスト。インターフェイスのインスタンス

私は次の(簡略化された)コードを持っています。

public class Controller
{
     private readonly IService _service;

     public Controller(IService service)
     {
         _service = service;
     }

     public async Task<IHttpActionResult> Create(MyObject object)
     {
         var result = _service.method(object);
         if (!result.Succeeded)
         {
            return this.GetErrorResult(object);
         }
     }
}

simpleInjectorは、次のように_serviceとその実装クラス間の依存関係を注入するために使用されます。

public static void Register(Container container)
{
    container.Register<IService, Service>();
}

注意として、インジェクションとユニットテストは私にとって新しいので、私はそれらを完全には理解していませんが、学んでいます。

Swaggerを介してアプリケーションを実行すると、すべて正常に機能しています。

注意として、Swaggerを介してアプリケーションを実行すると、Register関数が呼び出されます。

今、私はNUnitを使用していくつかの単体テストをセットアップしようとしており、次のようにIServiceオブジェクトをモックしています。

var Service = new Mock<IService>();
Controller _controller = new Controller(Service.Object);
_controller.Create(new MyObject object());

これは今のところ私には正しいようです-私にはわかりませんが?

問題は、単体テストの場合、resultが常にnullであるということです-インターフェイスのモックに問題があるためだと思います-メソッドを見つけていないようです-ステップインすることはありませんデバッガーには表示されません。

注意として、単体テストの場合、Registerメソッドは呼び出されません。依存関係を登録するためにそれを呼び出してみましたが、役に立ちません。

上で述べたように、これは私にとってまったく新しいことであり、私はこれらすべてについて理解の端にいます。

私はアイデアがなく、ここからどこを見ればよいかわからないので、どんな助けでも大歓迎です。

編集:

元の質問には次のものがありました。

public async Task<IHttpActionResult> Create(string content)

私が更新したもの:

public async Task<IHttpActionResult> Create(MyObject object)

このクラスのインスタンスを作成せずに、セットアップでMyObjectへの一般的な参照を渡す方法を誰かにアドバイスできますか?.

したがって、基本的には、このクラスのインスタンスは、そのインスタンスを作成せずに渡されることを伝えたいと思います。

私は以下を試しました:

Service.Setup(x => x.method(It.IsAny<MyObject>())

but it says cannot convert MethodGroup to MyObject

iServiceの定義は次のとおりです。

public interface IService
{
      IdentityResult method(ApplicationUser user, UserLoginInfo login);
}
5
Alex

次のように、IService.methodに対して何かを返すようにMockオブジェクトを構成する必要があります。

var Service = new Mock<IService>();
Service.Setup(x => x.method(It.IsAny<string>())
    .Returns<string>(str => **whatever result you need**);

実際のIService定義を追加したら、Setup呼び出しを次のように変更する必要があります。

Service.Setup(x => x.method(It.IsAny<ApplicationUser>(), It.IsAny<UserLoginInfo>())
    .Returns<ApplicationUser, UserLoginInfo>((user, login) => new IdentityResult(true));
2
Chris Pickford

Mockオブジェクトでsetupメソッドを呼び出す必要があります。

var Service = new Mock<IService>();
Service.Setup(x=>x.method("argument")).Returns(YourReturnObject)
Controller _controller = new Controller(Service.Object);
4
ganeshran

簡略化した例を使用する

public class Controller
{
     private readonly IService _service;

     public Controller(IService service)
     {
         _service = service;
     }

     public async Task<IHttpActionResult> Create(string content)
     {
         var result = await _service.method(content);
         if (!result.Succeeded)
         {
            return this.GetErrorResult(result);
         }
         return Ok();
     }
}

IServiceが次のように定義されていると仮定しましょう

public interface IService {
    Task<Result> method(string input);
}

public class Result {
    public bool Succeeded { get; set; }
}

単体テストでは、テストに必要なアクションを偽造するようにモックを設定する必要があります

public async Task Controller_Given_Content_Should_Return_Ok() {
    //Arrange
    var input = "content";
    var mockService = new Mock<IService>();
    mockService
        .Setup(m => m.method(input))
        .ReturnAsync(new Result { Succeeded = true }); 
    var _controller = new Controller(mockService.Object);

    //Act
    var result = await _controller.Create(input);

    //Assert
    Assert.IsNotNull(result);
    Assert.IsInstanceOfType(result,typeof(OkResult));
}

テスト対象のメソッドが非同期であるとすると、テストも非同期になるように設定する必要があります。

2
Nkosi