Closed tlenczyk closed 7 years ago
Hi
Are you sure its related to springmock?
I've just hacked something like this:
@Repository
public class DemoRepository {
public String message() {
return "hello";
}
}
@Service
public class DemoService {
public final DemoRepository demoRepository;
public DemoService(DemoRepository demoRepository) {
this.demoRepository = demoRepository;
}
public String getMessage() {
return demoRepository.message();
}
}
@RestController
@RequestMapping("/hello")
public class DemoController {
private final DemoService demoService;
public DemoController(DemoService demoService) {
this.demoService = demoService;
}
@RequestMapping
public DemoMessage message() {
return new DemoMessage(demoService.getMessage());
}
public static class DemoMessage {
private final String message;
public DemoMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
}
and the test:
@WebMvcTest(DemoController)
class DemoControllerTest extends Specification {
@Autowired
MockMvc mockMvc
@AutowiredMock
DemoService demoService
def "should work 1"() {
given:
demoService.getMessage() >> "mock1"
when:
final request = mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
then:
request
.andExpect(status().isOk())
.andExpect(jsonPath('$.message', is("mock1")))
}
def "should work 2"() {
given:
demoService.getMessage() >> "mock2"
when:
final request = mockMvc.perform(MockMvcRequestBuilders.get("/hello"))
then:
request
.andExpect(status().isOk())
.andExpect(jsonPath('$.message', is("mock2")))
}
}
and it works for me :)
dependencies I've used:
compile('org.springframework.boot:spring-boot-starter-web')
testCompile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.12'
testCompile('org.springframework.boot:spring-boot-starter-test')
testCompile group: 'org.spockframework', name: 'spock-core', version: '1.1-groovy-2.4'
testCompile group: 'org.spockframework', name: 'spock-spring', version: '1.1-groovy-2.4'
testCompile group: 'com.pchudzik.springmock', name: 'springmock-spock', version: '1.0.0'
are you using sprock 1.1 and spring-boot 1.4.4 spring 4.3.6?
Can you provide failing test case? If not maybe you'll find few minutes to debug and investigate what's going on inside com.pchudzik.springmock.spock.spring.MockAttachingTestExecutionListener.tryToGetBean (try to evaluate applicationContext.getBean(beanName) is it returning null? can you tell why?)
Maybe you have both junit and spock tests?
Hmm, strange. I will look at this again next week and let you know about details.
I can confirm that it is working on fresh (simplest) spring-boot project. After debugging I've noticed test is failing when trying to obtain bean instance with name "privilegeEvaluator" which is related to Spring Security. After disabling security in test:
@WebMvcTest(controllers = DemoController, secure = false)
class DemoControllerTest extends Specification {
everything works properly.
Leaving it open then. Will investigate what's going on.
Does your service by any chance depends on something related to security (some kind of principal, or something which might trigger spring security?) Or in general depends on something? I'm asking because maybe for some reason spring is trying to populate dependencies. Dependency processing should be ignored (SkipSpockBeansPostProcessing) but who knows maybe custom order should be added to this post processor or something. If you feel like it you can debug it and see what's going on and if SkipSpockBeansPostProcessing is called during getBean execution :)
Just out of curiosity can you check if @MockBean from springBoot works? I'm guessing it does :)
I've just checked it works just fine with spring security - https://github.com/pchudzik/springmock-spock-with-security-test but I might be missing something there.
@tlenczyk could you please check what you are doing differently in your project so that's not working. If you have time I'd really appreciate PR to springmock-spock-with-security-test which break it :)
For what exactly you are using privilegeEvaluator? Do you have your own implementation of this class? Do you have custom implementation of PermissionEvaluator? Have you checked is @MockBean is working (you can replace AutowiredMock with MockBean and use mockito to mock stuff)?
One more idea to check. Instead of walking whole context hierarchy take advantage of doubleregistry and try to use it to find doubles which are registered com.pchudzik.springmock.spock.spring.MockAttachingTestExecutionListener#beforeTestMethod
Don't walk whole context and fetch all definitions. Search for definitions with names already defined in doubleregistry. It should be enough (check if and how FactoryBeans are registered in the double registry).
When scanning only doubles which are registered and known to be mocks then early beans initialization might be avoided (NPE might be avoided if I will not touch security infrastructure while attaching mocks)
@tlenczyk please check latest springmock snapshot version. Since I wasn't able to reproduce the issue I'be been guessing what might be causing this issue but I think I might have come up with the solution to avoid it in the first place :)
Please verify and if it is still failing then reopen this.
Hi Paweł,
Great library. I'm going to use it for mocking dependencies for Spring MVC controller tests. Did you try it with @ WebMvcTest ?
now i'm having exception:
Do I understand correctly that in current version(1.0.0) it is not supported?