[JAVA] Summary of moss when updating from JMockit 1.4 to 1.30

When I raised it from Java8u74 to 8u102, it seemed that I had to raise JMockit as well. The JMockit I'm using is too old, and I'm afraid that it will cause a compile error or a runtime error. I decided to summarize it as a memorandum.

environment

Java8u102 (maybe 8u74 will work) maven3 series

change log It's mostly written, but sometimes I don't know how to actually write it. JMockit Development history

Sites that I mainly referred to

-JMockit usage memo I'm really grateful that it's mostly listed and how to write it in detail.

First, upgrade the library version

JMockit 1.4

pom.xml


		<dependency>
			<groupId>com.googlecode.jmockit</groupId>
			<artifactId>jmockit</artifactId>
			<version>1.4</version>
			<scope>test</scope>
		</dependency>

JMockit 1.30 I'm afraid that even the group has changed. (Although it is common ...)

pom.xml


		<dependency>
			<groupId>org.jmockit</groupId>
			<artifactId>jmockit</artifactId>
			<version>1.30</version>
			<scope>test</scope>
		</dependency>

1. Eliminate compilation errors

Change NonStrictExpectations to Expectations

It has been deprecated in Version 1.23 and deleted in Version 1.25.

Version 1.23 (Apr 24, 2016): Deprecated the NonStrictExpectations class. Existing tests should use Expectations instead.

Version 1.25 (Jun 26, 2016): Removed the NonStrictExpectations class, which was deprecated in version 1.23.

For the time being, I want to get rid of the compilation error, so I will change it blindly.

The usage of NonStrict Expectations is summarized in the following link (although it can not be used anymore) jMockit is good Verification

What is the difference between NonStrict Expectations and Expectations?

--Expectations Record all execution order, number of executions, etc. Quite strict. --NonStrictExpectations Loosen a little. Through whether it is executed or not.

There seems to be a difference like this. For details, please see the links below for easy understanding. Thanks. JMockit Usage Memo NonStrictExpectations This will be fixed later as it will fail when running the test.

@Mocked (methods = "readLine") or the one that specifies the argument in the annotation

Deprecated in Version 1.5 and "methods" and "inverse" attributes have been removed in Version 1.6.

Version 1.5 (Oct 20, 2013): Deprecated the "methods" and "inverse" attributes of @Mocked. Existing uses like @Mocked(methods = {"method1", "method2"}) should simply be rewritten as @Mocked({"method1", "method2"}) (using the default value attribute). As for the inverse attribute, specify what is to be mocked instead. Version 1.6 (Dec 23, 2013): Removed the "methods" and "inverse" attributes of the @Mocked annotation, which were deprecated in release 1.5. Tests still using "@Mocked(methods = {...}) should instead use the default "value" attribute.

This method will be removed in Version 1.19 even though I'm telling you to use @Mocked (methods = {...}) from now on. sad.

Version 1.19 (Aug 23, 2015): Removed the "value" attribute of @Mocked, which was deprecated in release 1.17. Existing tests using "@Mocked({"someMethod", "anotherMethod", ...})" should simply omit the attribute, or use partial mocking as applied with new Expectations(objToPartiallyMock) { ... }, or apply a MockUp class.

There are various ways to write with the arguments of Expectations after that, so I do not know whether it can be used or not, so Gently rewrite to MockUp .

Before correction.java


@Test
public void test(@Mocked(methods="readLine") final BufferedReader br) {
		new NonStrictExpectations() {
			{
				br.readLine();
				result = new IOException();
			}
		};
}

Revised.java


@Test
public void test() { // MockUp<T>Since it is defined in, the argument is deleted. If there is, it will be an error
		new MockUp<BufferedReader>() {
			@Mock
			public String readLine() throws IOException{
				throw new IOException();
			}
		};	
}

By the way, in this case of BufferedReader, it seems good to change @Mocked to @Injectable (or rather, both have the same result). I wonder which one is better. Click here for details → JMockit First Step @Injectable

change setField and invoke to static method of Deencapsulation

It seems that it was the Invocations class that operated on setField, invoke and private people, but it seems that it was deleted in Version 1.6.

Version 1.6 (Dec 23, 2013): Removed all Reflection-based utility methods from the Invocations class (the base for Expectations and Verifications), in favor of using the static methods of identical signatures in the Deencapsulation class. This change in the API will not require any changes to test code, except that test classes using these methods should now include the following "static import": import static mockit.Deencapsulation.*;

Before correction.java


setField(hoge, "aaaa", "aaaa");
invoke((hoge, "privateMethod");

After change.java


Deencapsulation.setField(hoge, "aaaa", "aaaa");
Deencapsulation.invoke((hoge, "privateMethod");

By the way, if you try to set it in the private static final field, you may get angry with Can not set static final, so in that case It seems that the behavior of Deencapsulation.setField has changed yukiko-kato-bass/items/69b0c7b2417079345d37#deencapsulationsetfield%E3%81%AE%E6%8C%99%E5%8B%95%E3%81%8C%E5%A4%89%E3%82%8F%E3% 81% A3% E3% 81% 9F% E3% 82% 89% E3% 81% 97% E3% 81% 84).

2. Fix any errors in the test

Missing 1 invocation to: ~ Caused by: Missing invocations Now the moss is [Change NonStrictExpectations to Expectations](http://qiita.com/yukiko-kato-bass/items/69b0c7b2417079345d37#nonstrictexpectations%E3%82%92expectations%E3%81%AB%E5%A4% 89% E6% 9B% B4% E3% 81% 99% E3% 82% 8B). This method isn't called! I'm angry. Sir Sen. It's an error because the method recording became strict. As a workaround, set the minimum expected number of executions of the method to 0. By the way, if you want to explicitly show that it is not called, you can check with maxTimes = 0.

HogeTest.java


        new Expectations() {{
            hoge.method(); minTimes=0;
            hoge.method2(); maxTimes=0;
        }};

~~ Well, if you put this on, you won't know if it was called or not, so I think you should check that area with Verifications. ~~

Has Enum's Mock been written differently?

The guy who writes this way now falls with a NullPointerException.

Before correction.java


@Test
public void test(@Mocked final HogeEnum hogeEnum) {

	new Expectations() {

		@Mocked
		HogeEnum hogeEnum;

		{
			hogeEnum.getHoge();
			result = "hogehoge";
		}
	};

Apparently it should be rewritten to MockUp. How to mock this in an Enum class using jmockt?

Revised.java


@Test
public void test() { //Since it is written in MockUp, delete the argument
	new MockUp<HogeEnum>() {
		@Mock
		public String getHoge() {
			return "/NOTHING/DATA.mf";
		}
	};
}

Change the behavior of Mock instance by changing from NonStrictExpectations to Expectations?

When I changed the one written like this from NonStrictExpectations to Expectations, it ended up failing.

Change before.java


    @Test
    public void test() throws Exception {
    	final Hoge hoge1 = new Hoge("hogehoge");
		new NonStrictExpectations() {
            {
                test.getHoge("hogehoge");
                result = hoge1;
            }
        };
        
        assertThat(test.getHoge("hogehoge"), hoge1);
        
        assertThat(test.getHoge("fugafuga"), null);  //It won't be null here!
    }

When I debugged, the Hoge instance itself was created. (Although value is null) If you look here, [JMockit usage memo Value returned by the method of the mocked object](http://qiita.com/opengl-8080/items/a49d4dae9067413ccdd6#%E3%83%A2%E3%83%83%E3 % 82% AF% E5% 8C% 96% E3% 81% 95% E3% 82% 8C% E3% 81% 9F% E3% 82% AA% E3% 83% 96% E3% 82% B8% E3% 82 % A7% E3% 82% AF% E3% 83% 88% E3% 81% AE% E3% 83% A1% E3% 82% BD% E3% 83% 83% E3% 83% 89% E3% 81% 8C % E8% BF% 94% E3% 81% 99% E5% 80% A4), so it's the behavior, but I want to change the object returned by the argument, or I want to return null when it is not a certain argument you know.

How to fix

Explicitly specify the result when the arguments are different

amendment.java


    @Test
    public void test() throws Exception {
    	final Hoge hoge1 = new Hoge("hogehoge");
		new Expectations() {
            {
                test.getHoge("hogehoge");
                result = hoge1;
                test.getHoge("fugafuga");
                result = null;
            }
        };
        
        assertThat(test.getHoge("hogehoge"), hoge1);
        
        assertThat(test.getHoge("fugafuga"), null);
    }

It seems that the behavior of Deencapsulation.setField has changed

Rewriting of private static final fields worked in 1.4, but it seems that the behavior has changed, and java.lang.RuntimeException: java.lang.IllegalAccessException: Can not set static final ~ has come to occur. (The target to be set is not a primitive. The set is a Mock object.) Deencapsulation.setField() is broken for JDK8 after I upgrade to v1.24

Ok, I updated our tests to use a MockUp instead. This is cleaner anyway.

Eh, can you use MockUp? So, [Mock static initialization block](http://qiita.com/opengl-8080/items/a49d4dae9067413ccdd6#static-%E5%88%9D%E6%9C%9F%E5%8C% 96% E3% 83% 96% E3% 83% AD% E3% 83% 83% E3% 82% AF% E3% 82% 92% E3% 83% A2% E3% 83% 83% E3% 82% AF% I rewrote it using E5% 8C% 96% E3% 81% 99% E3% 82% 8B) as a reference.

Hoge.java


//Application is a self-made class
private final static Application application = Application.getInstance();

Before correction.java


Hoge hoge = new Hoge();
Deencapsulation.setField(Hoge.class , application);

Revised.java


		new MockUp<Hoge>() {
			@Mock
			void $clinit() {
				Deencapsulation.setField(Hoge.class ,hoge);
			}
		};

Is it possible to assign with $ clinic () even if it is not declared in a static block? A mystery.

Deencapsulation.invoke also seems to have changed its behavior

Some of the invokes didn't work either. I don't know the difference between a moving one and a non-moving one. ..

PrivateHoge.java


//Suppose there is such a method
private Hoge getHoge() {
  return hoge;
}

Before correction.java


new Expectations() {{
  Deencapsulation.invoke(privateHoge, "getHoge");
}};

Rewrite using MockUp

Revised.java


		new Expectations() {{
			new MockUp<PrivateHoge>() {
				@Mock
				Hoge getHoge() {
					return hogehoge;
				}
			};
		}};

It seems that Deencapsulation.invoke can also be used if it is a Mockized method in MockUp. I'm saying NullPointer, so I wonder if I should make it explicit before invoking.

Amendment 2.java


		new Expectations() {{
			new MockUp<PrivateHoge>() {
				@Mock
				Hoge getHoge() {
					Deencapsulation.invoke(privateHoge, "getHoge");
				}
			};
		}};

It seems that the way of writing dynamic partial mocking has changed

Those who declared @Mocked instances in Expectations now return null. By the way, it seems that partial mocking is called Partial Mocking. really jMockit Verifications partial mocking

The one who got stuck.java


		new Expectations(patternManager) {
			@Mocked Hoge hoge;
			{
				System.out.println(hoge);
				System.out.println(hoge.hoge);

amendment

  1. Change to a unit test instance field
  2. Declare using @Mocked in the argument of the unit test execution method → [Define with test method arguments](http://qiita.com/opengl-8080/items/a49d4dae9067413ccdd6#%E3%83%86%E3%82%B9%E3%83%88%E3%83%A1 % E3% 82% BD% E3% 83% 83% E3% 83% 89% E3% 81% AE% E5% BC% 95% E6% 95% B0% E3% 81% A7% E5% AE% 9A% E7 % BE% A9% E3% 81% 99% E3% 82% 8B)

In either.

The return value of the constructor can no longer be returned

[Constructor return value cannot be specified](http://qiita.com/opengl-8080/items/a49d4dae9067413ccdd6#%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%88 % E3% 83% A9% E3% 82% AF% E3% 82% BF% E3% 81% AE% E6% 88% BB% E3% 82% 8A% E5% 80% A4% E3% 81% AF% E6 % 8C% 87% E5% AE% 9A% E3% 81% A7% E3% 81% 8D% E3% 81% AA% E3% 81% 84)

This is quite difficult and fighting

Alternative ①

As shown in Accessing the invocation context, it seems that the $ init method can do the same processing as the constructor. You just have to match the signature.

HogeTest.java


new MockUp<File>() {
      @Mock
      void $init(File file, String path)
      {
        // new File(file, path)Can be mocked in the constructor of
      }

By the way, if you add Invocation to the first argument, you can get a mock instance.

It seems that System class and native class should also be written in MockUp

Other sites that I referred to

-JMockit First Step -[JMockit1.30] More details on argument matching in Expectations

Recommended Posts

Summary of moss when updating from JMockit 1.4 to 1.30
[Eclipse] Summary of environment settings * Updated from time to time
From introduction to use of ActiveHash
From introduction to usage of byebug
Summary of results of research on object orientation [Updated from time to time]
From pulling docker-image of rails to launching
Summary of stumbling blocks related to form_with
Language summary to learn from now on
[java] Summary of how to handle char
Summary of means when you want to communicate with HTTP on Android
About virtualBox6.1.16, error resolution of shared folder when updating to CentOS Stream
Story when moving from Spring Boot 1.5 to 2.1
Changes when migrating from Spring Boot 1.5 to Spring Boot 2.0
Summary of going to JJUG CCC 2019 Spring
[Java] [Maven3] Summary of how to use Maven3
Changes when migrating from Spring Boot 2.0 to Spring Boot 2.2
Precautions when migrating from VB6.0 to JAVA
Troubleshooting when raising Mastodon from v3.0.x to v3.1.x
[Personal memo] Summary of stumbling blocks when deploying Rails apps to AWS
[Updating] It was difficult to upgrade from httpclient 3.x series to 4.5, so I will write a summary of changes
Summary of good points and precautions when converting Java Android application to Kotlin
[Promotion of Ruby comprehension (1)] When switching from Java to Ruby, first understand the difference.
Summary of how to select elements in Selenium
Summary of how to create JSF self-made tags
Things to be aware of when writing Java
[Docker] Introduction to docker compose Basic summary of docker-compose.yml
[Java] Summary of how to abbreviate lambda expressions
From setup to usage of Selenium wrapper Selenide
Precautions when converting from decimal number to binary number
[Ruby] Summary of how to get values from standard input [Paiza skill check measures]
Summary of how to use the proxy set in IE when connecting with Java
From the introduction of devise to the creation of the users table
When the hover of Eclipse is hard to see
How to write Scala from the perspective of Java
[Java Silver] Summary of points related to lambda expressions
The story of migrating from Paperclip to Active Storage
Things to be aware of when using devise's lockable
Summary of knowledge required to pass Java SE8 Silver
[JavaServlet] Summary of correspondence when Japanese parameters are garbled
Summary of Java communication API (1) How to use Socket
Summary of Java communication API (3) How to use SocketChannel
How to prevent editTextPreference of android PreferenceFragmentCompat from breaking
Summary of Java communication API (2) How to use HttpUrlConnection
Summary of how to implement default arguments in Java
Jet lag countermeasures when going from Japan to JavaOne
[Java] Things to be aware of when outputting FizzBuzz
[Ubuntu20.04] From ROS-noetic installation to SLAM simulation of turtlebot3
[Technical memo] Things to be careful of from an engineer's point of view when creating a view