injector icon indicating copy to clipboard operation
injector copied to clipboard

Question: Testing with injector

Open rudykocur opened this issue 6 years ago • 3 comments

Hi,

Thanks for this great project, it adds really nice separation to my code. But now I want to unittest everything and there are two cases:

  1. In documentation you show that we should use with_injector but it is depreciated and is spewing warnings in my tests
  2. Using with_injector I create mock service and unittest component which uses this service. But I would like to assert that mocked service was called with correct parameters. How can I obtain reference to mocked service? For now it seems I have to access self.__injector__ which seems a little hacky. Is there another way? Is there planned another way?

rudykocur avatar Feb 02 '18 08:02 rudykocur

Hi,

Replication with_injector's behaviour should be easy if you really need it but I'd like to understand the issue at hand first. Can you provide a code sample that demonstrates what you're doing? In general I don't think you should need or want to use injector in unit tests but we may be referring to different things using that term.

jstasiak avatar Feb 02 '18 21:02 jstasiak

I have a quite similar question to this topic, I work at the moment with the Injector and a Function that I want to test accesses the Injector.get and returns a class and calls a method. Now I would like to overwrite this method that it returns something that I want to set up in the first place.

    def test_start(self):
        subject = SubjectClass();
    
        Injector().get(Controller).get_project_by = Mock(
            return_value=Project("test_project", "test_owner", [], "0"))

       Injector().get(Repository).start_optimization = Mock(return_value="")

       subject.start_optimization() -> calls inside the Injector of Repository

        # The problems happens here
       Injector().get(Repository).start_optimization.assert_called_once()

md-weber avatar Nov 04 '20 12:11 md-weber

@md-weber what about this approach? I assume that there is some place where the injector is configured and, from my understand, it should be passed explicitly (or accessed as global) from the SubjectClass.


from unittest import mock 
def test_start():
    # Given
    mocked_controller = mock.Mock(spec=Controller)
    mocked_controller.get_project_by.return_value = Project("test_project", "test_owner", [], "0")

    mocked_repo = mock.Mock(spec=Repository)
    mocked_repo.start_optimization.return_value = ""

    def configure(binder):
        binder.bind(Controller, to=injector.InstanceProvider(mocked_controller))
        binder.bind(Repository, to=injector.InstanceProvider(mocked_repo))

    injector = Injector(configure)
    subject = SubjectClass(injector=injector)

    # When
    subject.start_optimization() 

    # Then
    mocked_repo.start_optimization.assert_called_once()
    

signalpillar avatar Nov 04 '20 20:11 signalpillar