Skip to content

TestNgToAssertj: emit a static import for assertThat instead of mirroring the source qualification (Assertions.assertThat) #1029

Description

@juherr

What version of OpenRewrite are you using?

rewrite-testing-frameworks 3.39.0 (the release that first covers the whole org.testng.Assert surface), recipe org.openrewrite.java.testing.testng.TestNgToAssertj.

What is the smallest, simplest way to reproduce the problem?

Given a source file that calls TestNG assertions through the qualified Assert. form (rather than a static import):

import org.testng.Assert;

class ExampleTest {
  void test() {
    Assert.assertNotNull(value);
    Assert.assertEquals(actual, expected);
    Assert.assertTrue(flag, "should be true");
  }
}

What did you expect to see?

Idiomatic AssertJ, with assertThat brought in as a static import (AssertJ's documented convention):

import static org.assertj.core.api.Assertions.assertThat;

class ExampleTest {
  void test() {
    assertThat(value).isNotNull();
    assertThat(actual).isEqualTo(expected);
    assertThat(flag).withFailMessage("should be true").isTrue();
  }
}

What did you see instead?

The recipe mirrors the source's qualification style: qualified Assert.assertX(...) calls become qualified Assertions.assertThat(...), while calls that were originally static-imported become static-imported assertThat(...).

import org.assertj.core.api.Assertions;

class ExampleTest {
  void test() {
    Assertions.assertThat(value).isNotNull();
    Assertions.assertThat(actual).isEqualTo(expected);
    Assertions.assertThat(flag).withFailMessage("should be true").isTrue();
  }
}

When a single class mixes both call styles, the output mixes both import forms — a static import static ...assertThat and a qualified import ...Assertions — in the same file.

Real-world impact

  • We used this recipe to migrate the entire TestNG test suite off org.testng.Assert in testng-team/testng#3278. The migration is correct, and we're grateful it now covers the whole Assert class. But because most of our code used the qualified Assert.assertX(...) form, the output is ~1500 Assertions.assertThat(...) calls across ~420 files, many with a mixed import style. A static import for assertThat would be noticeably more elegant and consistent with how AssertJ is normally written.

Suggestion

Could TestNgToAssertj normalize assertThat (and the other AssertJ entry points it introduces, e.g. assertThatThrownBy / assertThatExceptionOfType) to a static import regardless of how the original TestNG assertion was qualified — for example by composing org.openrewrite.java.UseStaticImport for org.assertj.core.api.Assertions *(..) as a cleanup step? That would also resolve the mixed-import case.

Related

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions