2017-06-02 14 views
2

私は私のリポジトリクラスをテストできるようにIServiceProvider用(部品番号を使用して)モックを作成しようとしています:以下のように部品番号IServiceProvider/IServiceScope

public class ApiResourceRepository : IApiResourceRepository 
{ 
    private readonly IServiceProvider _serviceProvider; 

    public ApiResourceRepository(IServiceProvider serviceProvider) 
    { 
     _serviceProvider = serviceProvider; 
     _dbSettings = dbSettings; 
    } 

    public async Task<ApiResource> Get(int id) 
    { 
     ApiResource result; 

     using (var serviceScope = _serviceProvider. 
      GetRequiredService<IServiceScopeFactory>().CreateScope()) 
     { 
      var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>(); 
      result = await 
       context.ApiResources 
       .Include(x => x.Scopes) 
       .Include(x => x.UserClaims) 
       .FirstOrDefaultAsync(x => x.Id == id); 
     } 

     return result; 
    } 
} 

モックオブジェクトを作成での私の試みは次のとおりです。

Mock<IServiceProvider> serviceProvider = new Mock<IServiceProvider>(); 

serviceProvider.Setup(x => x.GetRequiredService<ConfigurationDbContext>()) 
    .Returns(new ConfigurationDbContext(Options, StoreOptions)); 

Mock<IServiceScope> serviceScope = new Mock<IServiceScope>(); 

serviceScope.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object); 

serviceProvider.Setup(x => x.CreateScope()).Returns(serviceScope.Object); 

は、私は、次のエラーが発生します:すでに述べた

System.NotSupportedException : Expression references a method that does not belong to the mocked object: x => x.GetRequiredService()

+0

拡張メソッドですか?もしそうなら、あなたはそれをmoqできません。 – PmanAce

+0

はい、私は見ましたが、それは拡張メソッドのようです。私はIServiceProviderに依存しているので、このクラスをどのようにテストすることができるか見て苦労しています。 – blgrnboy

+0

可能な解決策については、この回答を確認してください。 [Moqを使った拡張メソッドのモック](https://stackoverflow.com/questions/2295960/mocking-extension-methods-with-moq) – PmanAce

答えて

5

として、部品番号Dを拡張メソッドの設定ができません。この場合

しかし前記拡張メソッドのソースコードは、GitHubの

ServiceProviderServiceExtensionsに入手可能です。

このような問題を回避する一般的な方法は、拡張メソッドが何を実行しているかを調べ、パスを実行中に安全にモックすることです。

基本タイプはIServiceProviderとそのobject Getservice(Type type)です。このメソッドは、サービスタイプを解決するときに最終的に呼び出されるメソッドです。そして、私たちは抽象度(インタフェース)を扱っているだけで、より簡単にmoqを使うことができます。

//Arrange 
var serviceProvider = new Mock<IServiceProvider>(); 
serviceProvider 
    .Setup(x => x.GetService(typeof(ConfigurationDbContext))) 
    .Returns(new ConfigurationDbContext(Options, StoreOptions)); 

var serviceScope = new Mock<IServiceScope>(); 
serviceScope.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object); 

var serviceScopeFactory = new Mock<IServiceScopeFactory>(); 
serviceScopeFactory 
    .Setup(x => x.CreateScope()) 
    .Returns(serviceScope.Object); 

serviceProvider 
    .Setup(x => x.GetService(typeof(IServiceScopeFactory))) 
    .Returns(serviceScopeFactory.Object); 

var sut = new ApiResourceRepository(serviceProvider.Object); 

//Act 
var actual = sut.Get(myIntValue); 

//Asssert 
//... 

テスト対象のメソッド(しゃれが意図していない)上記のコードを見直し、あなたは配置が拡張メソッドの期待される動作を満たし、拡張によってどのように見るであろう。