Use Gradle testfixtures.ProjectBuilder to create a Project for the unit tests (#1458)

* Use Gradle testfixtures.ProjectBuilder to create a Project for the unit tests

* Cleanup
This commit is contained in:
modmuss
2025-11-29 07:53:24 +00:00
committed by GitHub
parent bfabf091f6
commit ed0587df70
5 changed files with 8 additions and 251 deletions

View File

@@ -30,9 +30,7 @@ import java.util.stream.Stream
import groovy.transform.CompileStatic
import org.gradle.api.NamedDomainObjectList
import org.gradle.api.NamedDomainObjectProvider
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import spock.lang.Specification
import spock.lang.TempDir
@@ -193,14 +191,9 @@ class SpecContextTest extends Specification {
apiArtifacts[this.compileOnly].addAll(files.compileOnly)
}
private static void configureDependencies(List<Path> files, RemapConfigurationSettings settings) {
def configuration = mock(Configuration.class)
when(configuration.resolve()).thenReturn(files*.toFile() as Set)
def provider = mock(NamedDomainObjectProvider.class)
when(provider.get()).thenReturn(configuration)
when(settings.getSourceConfiguration()).thenReturn(provider)
private void configureDependencies(List<Path> files, RemapConfigurationSettings settings) {
project.configurations.register(settings.name)
project.dependencies.add(settings.name, project.files(files))
}
private Path mod(String modId) {

View File

@@ -1,61 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2025 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.fabricmc.loom.test.unit
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.provider.Property
import spock.lang.Specification
import net.fabricmc.loom.test.util.TestServiceFactory
class TestServiceFactoryTest extends Specification {
def "property"() {
setup:
def test = TestServiceFactory.objectFactory.newInstance(PropertyTest)
when:
test.example.set("hello")
then:
test.example.isPresent()
test.example.get() == "hello"
}
def "file property"() {
setup:
def test = TestServiceFactory.objectFactory.newInstance(FileTest)
when:
test.example.from(new File("test"))
then:
test.example.files.size() == 1
test.example.singleFile != null
}
interface PropertyTest {
Property<String> getExample()
}
interface FileTest {
ConfigurableFileCollection getExample()
}
}

View File

@@ -30,7 +30,7 @@ class MappingsServiceTest extends ServiceTestBase {
def "get mapping tree"() {
given:
def options = MappingsService.TYPE.create(project) {
it.mappingsFile.set(new File("src/test/resources/mappings/PosInChunk.mappings"))
it.mappingsFile.set(new File("src/test/resources/mappings/PosInChunk.mappings").absoluteFile)
it.from.set("intermediary")
it.to.set("named")
}

View File

@@ -25,7 +25,6 @@
package net.fabricmc.loom.test.util
import org.gradle.api.Project
import org.gradle.api.artifacts.ConfigurationContainer
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.file.RegularFile
import org.gradle.api.file.RegularFileProperty
@@ -34,9 +33,9 @@ import org.gradle.api.internal.tasks.DefaultSourceSet
import org.gradle.api.model.ObjectFactory
import org.gradle.api.plugins.ExtensionContainer
import org.gradle.api.provider.Property
import org.gradle.api.provider.ProviderFactory
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.util.PatternFilterable
import org.gradle.testfixtures.ProjectBuilder
import org.jspecify.annotations.Nullable
import org.mockito.invocation.InvocationOnMock
import org.mockito.stubbing.Answer
@@ -48,7 +47,6 @@ import net.fabricmc.loom.util.download.Download
import static org.mockito.ArgumentMatchers.any
import static org.mockito.Mockito.*
import static org.mockito.Mockito.mock
class GradleTestUtil {
static <T> Property<T> mockProperty(T value) {
@@ -66,26 +64,10 @@ class GradleTestUtil {
}
static Project mockProject() {
def project = mock(Project.class)
def serviceRegistry = TestServiceFactory.createServiceRegistry(project)
def objectFactory = serviceRegistry.get(ObjectFactory)
def providerFactory = serviceRegistry.get(ProviderFactory)
def extensions = mockExtensionContainer()
def configurationContainer = mock(ConfigurationContainer.class)
when(project.getExtensions()).thenReturn(extensions)
when(project.getObjects()).thenReturn(objectFactory)
when(project.provider(any())).thenAnswer {
providerFactory.provider(it.getArgument(0))
}
when(project.getConfigurations()).thenReturn(configurationContainer)
return project
}
static ExtensionContainer mockExtensionContainer() {
def mock = mock(ExtensionContainer.class)
def extension = mockLoomGradleExtension()
when(mock.getByName("loom")).thenReturn(extension)
return mock
def realProject = ProjectBuilder.builder().build()
realProject.extensions.add("loom", extension)
return realProject
}
static LoomGradleExtension mockLoomGradleExtension() {

View File

@@ -1,157 +0,0 @@
/*
* This file is part of fabric-loom, licensed under the MIT License (MIT).
*
* Copyright (c) 2025 FabricMC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.fabricmc.loom.test.util
import groovy.transform.CompileStatic
import org.gradle.api.Project
import org.gradle.api.internal.CollectionCallbackActionDecorator
import org.gradle.api.internal.MutationGuard
import org.gradle.api.internal.MutationGuards
import org.gradle.api.internal.collections.DefaultDomainObjectCollectionFactory
import org.gradle.api.internal.collections.DomainObjectCollectionFactory
import org.gradle.api.internal.file.DefaultFileCollectionFactory
import org.gradle.api.internal.file.DefaultFileLookup
import org.gradle.api.internal.file.DefaultFilePropertyFactory
import org.gradle.api.internal.file.FileCollectionFactory
import org.gradle.api.internal.file.FilePropertyFactory
import org.gradle.api.internal.file.FileResolver
import org.gradle.api.internal.file.collections.DirectoryFileTreeFactory
import org.gradle.api.internal.model.DefaultObjectFactory
import org.gradle.api.internal.model.NamedObjectInstantiator
import org.gradle.api.internal.provider.DefaultPropertyFactory
import org.gradle.api.internal.provider.DefaultProviderFactory
import org.gradle.api.internal.provider.PropertyFactory
import org.gradle.api.internal.provider.PropertyHost
import org.gradle.api.internal.tasks.DefaultTaskDependencyFactory
import org.gradle.api.internal.tasks.properties.annotations.OutputPropertyRoleAnnotationHandler
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.ProviderFactory
import org.gradle.api.tasks.util.internal.PatternSetFactory
import org.gradle.cache.internal.CrossBuildInMemoryCacheFactory
import org.gradle.cache.internal.DefaultCrossBuildInMemoryCacheFactory
import org.gradle.internal.event.ListenerManager
import org.gradle.internal.instantiation.InstantiatorFactory
import org.gradle.internal.instantiation.generator.DefaultInstantiatorFactory
import org.gradle.internal.instantiation.managed.DefaultManagedObjectRegistry
import org.gradle.internal.instantiation.managed.ManagedObjectRegistry
import org.gradle.internal.nativeintegration.filesystem.FileSystem
import org.gradle.internal.service.DefaultServiceRegistry
import org.gradle.internal.service.Provides
import org.gradle.internal.service.ServiceRegistrationProvider
import org.gradle.internal.service.ServiceRegistry
import static org.mockito.Mockito.mock
/**
* Based on Gradle's own TestUtils, this class setups the Gradle DI system to be used within unit tests.
*/
@CompileStatic
class TestServiceFactory {
public static final ServiceRegistry serviceRegistry = createServiceRegistry()
public static final ObjectFactory objectFactory = serviceRegistry.get(ObjectFactory)
public static final ProviderFactory providerFactory = serviceRegistry.get(ProviderFactory)
static ServiceRegistry createServiceRegistry(Project project = null) {
def services = new DefaultServiceRegistry()
services.register {
it.add(PropertyFactory, new DefaultPropertyFactory(PropertyHost.NO_OP))
it.add(ProviderFactory, new DefaultProviderFactory())
it.add(PropertyHost, PropertyHost.NO_OP)
it.add(NamedObjectInstantiator)
it.add(CollectionCallbackActionDecorator, CollectionCallbackActionDecorator.NOOP)
it.add(MutationGuard, MutationGuards.identity())
it.add(FileCollectionFactory, fileCollectionFactory())
it.add(DefaultDomainObjectCollectionFactory)
it.add(CrossBuildInMemoryCacheFactory, new DefaultCrossBuildInMemoryCacheFactory(mock(ListenerManager)))
if (project != null) {
it.add(Project, project)
}
//noinspection unused
it.addProvider(new ServiceRegistrationProvider() {
@Provides
ManagedObjectRegistry createManagedObjectRegistry() {
new DefaultManagedObjectRegistry()
}
@Provides
InstantiatorFactory createInstantiatorFactory(
CrossBuildInMemoryCacheFactory crossBuildInMemoryCacheFactory) {
return new DefaultInstantiatorFactory(
crossBuildInMemoryCacheFactory,
[],
new OutputPropertyRoleAnnotationHandler([]))
}
@Provides
FilePropertyFactory createFilePropertyFactory(
PropertyHost propertyHost,
FileCollectionFactory fileCollectionFactory) {
return new DefaultFilePropertyFactory(
propertyHost,
fileResolver(),
fileCollectionFactory)
}
@Provides
ObjectFactory createObjectFactory(
InstantiatorFactory instantiatorFactory,
NamedObjectInstantiator namedObjectInstantiator,
PropertyFactory propertyFactory,
FilePropertyFactory filePropertyFactory,
FileCollectionFactory fileCollectionFactory,
DomainObjectCollectionFactory domainObjectCollectionFactory) {
return new DefaultObjectFactory(
instantiatorFactory.decorate(services),
namedObjectInstantiator,
mock(DirectoryFileTreeFactory),
mock(PatternSetFactory),
propertyFactory,
filePropertyFactory,
DefaultTaskDependencyFactory.withNoAssociatedProject(),
fileCollectionFactory,
domainObjectCollectionFactory)
}
})
}
return services
}
private static FileResolver fileResolver() {
return new DefaultFileLookup().getFileResolver(new File(".").absoluteFile)
}
private static FileCollectionFactory fileCollectionFactory() {
return new DefaultFileCollectionFactory(
fileResolver(),
DefaultTaskDependencyFactory.withNoAssociatedProject(),
mock(DirectoryFileTreeFactory),
mock(PatternSetFactory),
PropertyHost.NO_OP,
mock(FileSystem))
}
}