Powermock: How to mock a method in an enumeration constant
I have an enumeration type which I used as a collection of factories for other objects that implement a common interface. A simplified version of the code is:
interface Operation {
void execute();
}
enum Factory {
TYPE1(Class1::new),
TYPE2(Class2::new);
private Supplier<Operation> constructor;
Factory(Supplier<Operation> constructor) {
this.constructor = constructor;
}
Operation build() {
return constructor.get();
}
}
A simplified version of the client code looks like:
class Client {
private void run(EnumSet<Factory> required) {
for (Factory x : required) {
x.build().execute();
}
}
// Some code that calls run() with the right EnumSet
}
This all appears to work as expected, so I want to write some Unit tests.
Testing the Factory
is easy, but the Client
is proving more difficult. The problem is that I don't want to start calling the Operation
(they do a lot of work). Instead I'd like to get x.build()
return a mock object.
I've tried using PowerMocks whenNew
to trap the creation of the Operation
objects, but this doesn't work (I don't actually have any 'new' operations). I've also tried to use a Powermock 'spy', but this fails because the enumeration constants are real objects.
Any ideas?
java unit-testing mocking powermock powermockito
add a comment |
I have an enumeration type which I used as a collection of factories for other objects that implement a common interface. A simplified version of the code is:
interface Operation {
void execute();
}
enum Factory {
TYPE1(Class1::new),
TYPE2(Class2::new);
private Supplier<Operation> constructor;
Factory(Supplier<Operation> constructor) {
this.constructor = constructor;
}
Operation build() {
return constructor.get();
}
}
A simplified version of the client code looks like:
class Client {
private void run(EnumSet<Factory> required) {
for (Factory x : required) {
x.build().execute();
}
}
// Some code that calls run() with the right EnumSet
}
This all appears to work as expected, so I want to write some Unit tests.
Testing the Factory
is easy, but the Client
is proving more difficult. The problem is that I don't want to start calling the Operation
(they do a lot of work). Instead I'd like to get x.build()
return a mock object.
I've tried using PowerMocks whenNew
to trap the creation of the Operation
objects, but this doesn't work (I don't actually have any 'new' operations). I've also tried to use a Powermock 'spy', but this fails because the enumeration constants are real objects.
Any ideas?
java unit-testing mocking powermock powermockito
Any feedback on my answer? If you found it helpful, pls dont forget about accepting, otherwise let me know if I can add anything to it ...
– GhostCat
Nov 15 at 15:50
Hi, I've been playing with the Powermock solution over the last couple of days, but I've not been able to get it to work :-( In the linked question the enumeration contained an abstract method which is why (I think) the individual constants have their own class. In this case there are no abstract methods, so the compiler only produces a single class file.
– Stormcloud
Nov 16 at 11:15
I see. But as said: I consider PowerMock(ito) to always be the last straw. If possible, change your production code, and make it easier to test. Anything else is using black magic to circumvent a designed-in deficiency.
– GhostCat
Nov 16 at 11:30
For the moment my work around is to add a setter function to the enumeration constants so thatbuild()
can return prebuilt objects - my mocks. While it means I've only made a small change to the production code it does mean that my enumeration 'constant' is now mutable! This feels worse then the alternatives.
– Stormcloud
Nov 16 at 11:58
add a comment |
I have an enumeration type which I used as a collection of factories for other objects that implement a common interface. A simplified version of the code is:
interface Operation {
void execute();
}
enum Factory {
TYPE1(Class1::new),
TYPE2(Class2::new);
private Supplier<Operation> constructor;
Factory(Supplier<Operation> constructor) {
this.constructor = constructor;
}
Operation build() {
return constructor.get();
}
}
A simplified version of the client code looks like:
class Client {
private void run(EnumSet<Factory> required) {
for (Factory x : required) {
x.build().execute();
}
}
// Some code that calls run() with the right EnumSet
}
This all appears to work as expected, so I want to write some Unit tests.
Testing the Factory
is easy, but the Client
is proving more difficult. The problem is that I don't want to start calling the Operation
(they do a lot of work). Instead I'd like to get x.build()
return a mock object.
I've tried using PowerMocks whenNew
to trap the creation of the Operation
objects, but this doesn't work (I don't actually have any 'new' operations). I've also tried to use a Powermock 'spy', but this fails because the enumeration constants are real objects.
Any ideas?
java unit-testing mocking powermock powermockito
I have an enumeration type which I used as a collection of factories for other objects that implement a common interface. A simplified version of the code is:
interface Operation {
void execute();
}
enum Factory {
TYPE1(Class1::new),
TYPE2(Class2::new);
private Supplier<Operation> constructor;
Factory(Supplier<Operation> constructor) {
this.constructor = constructor;
}
Operation build() {
return constructor.get();
}
}
A simplified version of the client code looks like:
class Client {
private void run(EnumSet<Factory> required) {
for (Factory x : required) {
x.build().execute();
}
}
// Some code that calls run() with the right EnumSet
}
This all appears to work as expected, so I want to write some Unit tests.
Testing the Factory
is easy, but the Client
is proving more difficult. The problem is that I don't want to start calling the Operation
(they do a lot of work). Instead I'd like to get x.build()
return a mock object.
I've tried using PowerMocks whenNew
to trap the creation of the Operation
objects, but this doesn't work (I don't actually have any 'new' operations). I've also tried to use a Powermock 'spy', but this fails because the enumeration constants are real objects.
Any ideas?
java unit-testing mocking powermock powermockito
java unit-testing mocking powermock powermockito
asked Nov 13 at 14:51
Stormcloud
9941925
9941925
Any feedback on my answer? If you found it helpful, pls dont forget about accepting, otherwise let me know if I can add anything to it ...
– GhostCat
Nov 15 at 15:50
Hi, I've been playing with the Powermock solution over the last couple of days, but I've not been able to get it to work :-( In the linked question the enumeration contained an abstract method which is why (I think) the individual constants have their own class. In this case there are no abstract methods, so the compiler only produces a single class file.
– Stormcloud
Nov 16 at 11:15
I see. But as said: I consider PowerMock(ito) to always be the last straw. If possible, change your production code, and make it easier to test. Anything else is using black magic to circumvent a designed-in deficiency.
– GhostCat
Nov 16 at 11:30
For the moment my work around is to add a setter function to the enumeration constants so thatbuild()
can return prebuilt objects - my mocks. While it means I've only made a small change to the production code it does mean that my enumeration 'constant' is now mutable! This feels worse then the alternatives.
– Stormcloud
Nov 16 at 11:58
add a comment |
Any feedback on my answer? If you found it helpful, pls dont forget about accepting, otherwise let me know if I can add anything to it ...
– GhostCat
Nov 15 at 15:50
Hi, I've been playing with the Powermock solution over the last couple of days, but I've not been able to get it to work :-( In the linked question the enumeration contained an abstract method which is why (I think) the individual constants have their own class. In this case there are no abstract methods, so the compiler only produces a single class file.
– Stormcloud
Nov 16 at 11:15
I see. But as said: I consider PowerMock(ito) to always be the last straw. If possible, change your production code, and make it easier to test. Anything else is using black magic to circumvent a designed-in deficiency.
– GhostCat
Nov 16 at 11:30
For the moment my work around is to add a setter function to the enumeration constants so thatbuild()
can return prebuilt objects - my mocks. While it means I've only made a small change to the production code it does mean that my enumeration 'constant' is now mutable! This feels worse then the alternatives.
– Stormcloud
Nov 16 at 11:58
Any feedback on my answer? If you found it helpful, pls dont forget about accepting, otherwise let me know if I can add anything to it ...
– GhostCat
Nov 15 at 15:50
Any feedback on my answer? If you found it helpful, pls dont forget about accepting, otherwise let me know if I can add anything to it ...
– GhostCat
Nov 15 at 15:50
Hi, I've been playing with the Powermock solution over the last couple of days, but I've not been able to get it to work :-( In the linked question the enumeration contained an abstract method which is why (I think) the individual constants have their own class. In this case there are no abstract methods, so the compiler only produces a single class file.
– Stormcloud
Nov 16 at 11:15
Hi, I've been playing with the Powermock solution over the last couple of days, but I've not been able to get it to work :-( In the linked question the enumeration contained an abstract method which is why (I think) the individual constants have their own class. In this case there are no abstract methods, so the compiler only produces a single class file.
– Stormcloud
Nov 16 at 11:15
I see. But as said: I consider PowerMock(ito) to always be the last straw. If possible, change your production code, and make it easier to test. Anything else is using black magic to circumvent a designed-in deficiency.
– GhostCat
Nov 16 at 11:30
I see. But as said: I consider PowerMock(ito) to always be the last straw. If possible, change your production code, and make it easier to test. Anything else is using black magic to circumvent a designed-in deficiency.
– GhostCat
Nov 16 at 11:30
For the moment my work around is to add a setter function to the enumeration constants so that
build()
can return prebuilt objects - my mocks. While it means I've only made a small change to the production code it does mean that my enumeration 'constant' is now mutable! This feels worse then the alternatives.– Stormcloud
Nov 16 at 11:58
For the moment my work around is to add a setter function to the enumeration constants so that
build()
can return prebuilt objects - my mocks. While it means I've only made a small change to the production code it does mean that my enumeration 'constant' is now mutable! This feels worse then the alternatives.– Stormcloud
Nov 16 at 11:58
add a comment |
1 Answer
1
active
oldest
votes
Two solutions:
- you insist on using PowerMock(ito). Then the simple issue is: you are probably preparing the wrong class for test. You have to temper with those enum constants, and they are inner classes. But it is possible, see this answer for example.
- you step back, and improve your production code, to make it easier to test.
For example like this:
interface OperationProvider {
Operation build();
}
to be used like:
enum Factory implements OperationProvider {
And now you can change your client code to do
OperationProvider ourProvider = ...
whatever.build();...
The point is: when using dependency injection, you simply pass a mocked OperationProvider. This means that you can basically sidestep the need to mock with your enum completely. You just have to make sure that within your production code, you obviously pass one of the enum constants when initializing that ourProvider
field for example.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53283659%2fpowermock-how-to-mock-a-method-in-an-enumeration-constant%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Two solutions:
- you insist on using PowerMock(ito). Then the simple issue is: you are probably preparing the wrong class for test. You have to temper with those enum constants, and they are inner classes. But it is possible, see this answer for example.
- you step back, and improve your production code, to make it easier to test.
For example like this:
interface OperationProvider {
Operation build();
}
to be used like:
enum Factory implements OperationProvider {
And now you can change your client code to do
OperationProvider ourProvider = ...
whatever.build();...
The point is: when using dependency injection, you simply pass a mocked OperationProvider. This means that you can basically sidestep the need to mock with your enum completely. You just have to make sure that within your production code, you obviously pass one of the enum constants when initializing that ourProvider
field for example.
add a comment |
Two solutions:
- you insist on using PowerMock(ito). Then the simple issue is: you are probably preparing the wrong class for test. You have to temper with those enum constants, and they are inner classes. But it is possible, see this answer for example.
- you step back, and improve your production code, to make it easier to test.
For example like this:
interface OperationProvider {
Operation build();
}
to be used like:
enum Factory implements OperationProvider {
And now you can change your client code to do
OperationProvider ourProvider = ...
whatever.build();...
The point is: when using dependency injection, you simply pass a mocked OperationProvider. This means that you can basically sidestep the need to mock with your enum completely. You just have to make sure that within your production code, you obviously pass one of the enum constants when initializing that ourProvider
field for example.
add a comment |
Two solutions:
- you insist on using PowerMock(ito). Then the simple issue is: you are probably preparing the wrong class for test. You have to temper with those enum constants, and they are inner classes. But it is possible, see this answer for example.
- you step back, and improve your production code, to make it easier to test.
For example like this:
interface OperationProvider {
Operation build();
}
to be used like:
enum Factory implements OperationProvider {
And now you can change your client code to do
OperationProvider ourProvider = ...
whatever.build();...
The point is: when using dependency injection, you simply pass a mocked OperationProvider. This means that you can basically sidestep the need to mock with your enum completely. You just have to make sure that within your production code, you obviously pass one of the enum constants when initializing that ourProvider
field for example.
Two solutions:
- you insist on using PowerMock(ito). Then the simple issue is: you are probably preparing the wrong class for test. You have to temper with those enum constants, and they are inner classes. But it is possible, see this answer for example.
- you step back, and improve your production code, to make it easier to test.
For example like this:
interface OperationProvider {
Operation build();
}
to be used like:
enum Factory implements OperationProvider {
And now you can change your client code to do
OperationProvider ourProvider = ...
whatever.build();...
The point is: when using dependency injection, you simply pass a mocked OperationProvider. This means that you can basically sidestep the need to mock with your enum completely. You just have to make sure that within your production code, you obviously pass one of the enum constants when initializing that ourProvider
field for example.
answered Nov 14 at 9:11
GhostCat
88.1k1684144
88.1k1684144
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53283659%2fpowermock-how-to-mock-a-method-in-an-enumeration-constant%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Any feedback on my answer? If you found it helpful, pls dont forget about accepting, otherwise let me know if I can add anything to it ...
– GhostCat
Nov 15 at 15:50
Hi, I've been playing with the Powermock solution over the last couple of days, but I've not been able to get it to work :-( In the linked question the enumeration contained an abstract method which is why (I think) the individual constants have their own class. In this case there are no abstract methods, so the compiler only produces a single class file.
– Stormcloud
Nov 16 at 11:15
I see. But as said: I consider PowerMock(ito) to always be the last straw. If possible, change your production code, and make it easier to test. Anything else is using black magic to circumvent a designed-in deficiency.
– GhostCat
Nov 16 at 11:30
For the moment my work around is to add a setter function to the enumeration constants so that
build()
can return prebuilt objects - my mocks. While it means I've only made a small change to the production code it does mean that my enumeration 'constant' is now mutable! This feels worse then the alternatives.– Stormcloud
Nov 16 at 11:58