在单元测试中模拟注入的场

时间:2016-11-05 20:27:02

标签: java android unit-testing mockito

我有一个Presenter类使用通过Dagger注入的字段,它看起来像这样:

public class RssListPresenter {

    @Inject
    RssService rssService; // <-- injected field

    public RssListPresenter() {
        setupDI();
    }

    private void setupDI() {
        DaggerNetworkComponent.builder()
                .networkModule(new NetworkModule())
                .build()
                .inject(this);
    }

    public void loadItems() {
        Rss rss = rssService.getRssFeed()
        // ....
    }
}

一切正常。现在,我想对RssListPresenter类进行单元测试。问题是我如何向演示者提供模拟RssService

当然我可以向演示者添加一个新方法setRssService(RssService rssService)并使用它来提供单元测试的模拟,但是仅为单元测试添加此方法感觉不对。处理这个问题的正确方法是什么?

为了完整性,这里是模块和组件声明:

@Singleton
@Component(modules = NetworkModule.class)
public interface NetworkComponent {
    void inject(RssListPresenter presenter);
}

@Module
public class NetworkModule {

    @Provides
    Retrofit provideRetrofit() {
        // ... 
    }

    @Provides
    @Singleton
    RssService providePcWorldRssService(Retrofit retrofit) {
        return retrofit.create(RssService.class);
    }

}

2 个答案:

答案 0 :(得分:6)

属性注入就像测试那么容易。在这种情况下,构造函数注入要好得多。将构造函数重构为如下所示:

var myObject1 = function() {

  var x = 0;

  return{}
}();

var myObject2 = function() {

  return{
    increment: function() {
        myObject1.x +=1;
        console.log(myObject1.x);
    }
  }
}();

myObject2.increment(); 

现在您可以轻松地进行测试:

private final RssService rssService;

@Inject
public RssListPresenter(RssService rssService) {
        this.rssService = rssService;
}

您可能不应该在//mocks RssService mockRssService; //system under test RssListPresenter rssListPresenter; @Before public void setup() { mockRssService = Mockito.mock(RssService.class); rssListPresenter = new RssListPresenter(mockRssService); } 内使用DaggerNetworkComponent.inject(this)。相反,您应该配置dagger,以便在将成员注入顶级类(RssListPresenterActivityFragment)时,它可以访问对象图并创建{的实例{1}}。

为什么只将注射器放在ServiceRssPresenter而不是Activity?这些是由Android系统实例化的类,因此您别无选择,只能使用注入器。

澄清一下,ServiceRssListPresenter等是理想的注射目标Activity注入依赖项。您需要配置依赖注入框架,dagger,以便它可以提供正确的依赖关系以注入注入目标。

因此,您还需要为Fragment

编写RssListPresenter方法
@Provides

答案 1 :(得分:0)

您的课程违反了某些S.O.L.I.D原则,这使得对其进行单元测试非常困难。您的班级肯定违反了SRP(单一责任原则),因为它有多个的原因需要更改。还存在可能的依赖性倒置违规。

我建议重新考虑类的模型,以便每个类执行特定的功能,并有一个改变的理由。