Skip to content
This repository was archived by the owner on May 16, 2026. It is now read-only.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.openelements.hiero.base;

import java.io.IOException;
import java.nio.file.Path;

public interface IFileReader {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree with this approach. Instead of mocking the Fiel read in the test you can easily create a test file and use that one in the tests

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review, and I've worked on them as requested.

byte[] readAllBytes(Path path) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.hedera.hashgraph.sdk.FileId;
import com.openelements.hiero.base.FileClient;
import com.openelements.hiero.base.HieroException;
import com.openelements.hiero.base.IFileReader;
import com.openelements.hiero.base.SmartContractClient;
import com.openelements.hiero.base.data.ContractCallResult;
import com.openelements.hiero.base.data.ContractParam;
Expand All @@ -28,10 +29,12 @@ public class SmartContractClientImpl implements SmartContractClient {
private final ProtocolLayerClient protocolLayerClient;

private final FileClient fileClient;
private final IFileReader fileReader;

public SmartContractClientImpl(@NonNull final ProtocolLayerClient protocolLayerClient, FileClient fileClient) {
public SmartContractClientImpl(@NonNull final ProtocolLayerClient protocolLayerClient, FileClient fileClient, IFileReader fileReader) {
this.protocolLayerClient = Objects.requireNonNull(protocolLayerClient, "protocolLevelClient must not be null");
this.fileClient = Objects.requireNonNull(fileClient, "fileClient must not be null");
this.fileReader = Objects.requireNonNull(fileReader, "fileReader must not be null");
}

@NonNull
Expand Down Expand Up @@ -74,7 +77,7 @@ public ContractId createContract(@NonNull final Path pathToBin,
@Nullable final ContractParam<?>... constructorParams)
throws HieroException {
try {
final byte[] bytes = Files.readAllBytes(pathToBin);
final byte[] bytes = fileReader.readAllBytes(pathToBin);
return createContract(bytes, constructorParams);
} catch (Exception e) {
throw new HieroException("Failed to create contract from path " + pathToBin, e);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.openelements.hiero.base.implementation;

import com.openelements.hiero.base.IFileReader;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class SystemFileReader implements IFileReader {
@Override
public byte[] readAllBytes(Path path) throws IOException {
return Files.readAllBytes(path);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
package com.openelements.hiero.base.test;

import com.hedera.hashgraph.sdk.ContractId;
import com.hedera.hashgraph.sdk.FileId;
import com.openelements.hiero.base.FileClient;
import com.openelements.hiero.base.HieroException;
import com.openelements.hiero.base.IFileReader;
import com.openelements.hiero.base.data.ContractParam;
import com.openelements.hiero.base.implementation.SmartContractClientImpl;
import com.openelements.hiero.base.protocol.ProtocolLayerClient;
import com.openelements.hiero.base.protocol.data.ContractCreateRequest;
import com.openelements.hiero.base.protocol.data.ContractCreateResult;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;

import java.io.IOException;
import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;


public class SmartContractClientImplTest {

@Mock
private FileClient fileClient;

@Mock
private ProtocolLayerClient protocolLayerClient;

@Mock
private IFileReader fileReader;

@InjectMocks
private SmartContractClientImpl smartContractClient;

private ContractId returnedContractId;

private ContractId contractId;

private FileId fileId;

private ContractParam<?> constructorParams;

private ContractCreateResult resultMock;

private Path path;

private byte[] contents;


@BeforeEach
public void init() throws IOException {
fileClient = Mockito.mock(FileClient.class);
protocolLayerClient = Mockito.mock(ProtocolLayerClient.class);
fileReader= Mockito.mock(IFileReader.class);
smartContractClient = Mockito.spy(new SmartContractClientImpl(protocolLayerClient, fileClient, fileReader));
contractId = ContractId.fromString("0.0.123");
fileId = FileId.fromString("0.0.123");
constructorParams = ContractParam.string("paramValue");
resultMock = Mockito.mock(ContractCreateResult.class);
path= Mockito.mock(Path.class);
contents = "contractBytecode".getBytes();


}

@Test
public void testCreateContract_UsingFileId_WithContractParams() throws HieroException {

when(resultMock.contractId()).thenReturn(contractId);
when(protocolLayerClient.executeContractCreateTransaction(any(ContractCreateRequest.class))).thenReturn(resultMock);

returnedContractId = smartContractClient.createContract(fileId, constructorParams);

assertEquals(contractId, returnedContractId);
verify(protocolLayerClient).executeContractCreateTransaction(any());

}

@Test
public void testCreateContract_UsingFileId_WithOutContractParams() throws HieroException {

when(resultMock.contractId()).thenReturn(contractId);
when(protocolLayerClient.executeContractCreateTransaction(any(ContractCreateRequest.class))).thenReturn(resultMock);

returnedContractId = smartContractClient.createContract(fileId);

assertEquals(contractId, returnedContractId);
verify(protocolLayerClient).executeContractCreateTransaction(any());
}

@Test
public void testCreateContract_UsingFileId_ThrowsException() throws HieroException {

when(protocolLayerClient.executeContractCreateTransaction(Mockito.any())).thenThrow(new RuntimeException("Failed"));
HieroException hieroException = assertThrows(HieroException.class, () -> smartContractClient.createContract(fileId, constructorParams));

assertTrue(hieroException.getMessage().contains("Failed to create contract with fileId " + fileId));
}

@Test
public void testCreateContract_UsingContent_WithContractParams() throws HieroException {

when(fileClient.createFile(contents)).thenReturn(fileId);
when(protocolLayerClient.executeContractCreateTransaction(any(ContractCreateRequest.class))).thenReturn(resultMock);
when(resultMock.contractId()).thenReturn(contractId);

returnedContractId = smartContractClient.createContract(contents, constructorParams);

assertEquals(contractId, returnedContractId);
verify(fileClient).createFile(contents);
verify(protocolLayerClient).executeContractCreateTransaction(any());
verify(fileClient).deleteFile(fileId);

}

@Test
public void testCreateContract_UsingContent_WithOutContractParams() throws HieroException {

when(fileClient.createFile(contents)).thenReturn(fileId);
when(protocolLayerClient.executeContractCreateTransaction(any(ContractCreateRequest.class))).thenReturn(resultMock);
when(resultMock.contractId()).thenReturn(contractId);

returnedContractId = smartContractClient.createContract(contents);

assertEquals(contractId, returnedContractId);
verify(fileClient).createFile(contents);
verify(protocolLayerClient).executeContractCreateTransaction(any());
verify(fileClient).deleteFile(fileId);
}

@Test
public void testCreateContract_UsingContent_ThrowsException() throws HieroException {
when(protocolLayerClient.executeContractCreateTransaction(Mockito.any())).thenThrow(new RuntimeException("Failed"));
HieroException hieroException = assertThrows(HieroException.class, () -> smartContractClient.createContract(contents, constructorParams));

assertTrue(hieroException.getMessage().contains("Failed to create contract out of byte array"));

}

@Test
public void testCreateContract_UsingPath_WithContractParams() throws HieroException, IOException {

when(fileReader.readAllBytes(path)).thenReturn(contents);
doReturn(contractId).when(smartContractClient).createContract(contents, constructorParams);

returnedContractId = smartContractClient.createContract(path, constructorParams);

assertNotNull(returnedContractId);
assertEquals(contractId, returnedContractId);

verify(fileReader).readAllBytes(path);
verify(smartContractClient).createContract(contents, constructorParams);


}

@Test
public void testCreateContract_UsingPath_WithOutContractParams() throws HieroException, IOException {
when(fileReader.readAllBytes(path)).thenReturn(contents);
doReturn(contractId).when(smartContractClient).createContract(contents);

returnedContractId = smartContractClient.createContract(path);

assertNotNull(returnedContractId);
assertEquals(contractId, returnedContractId);

verify(fileReader).readAllBytes(path);
verify(smartContractClient).createContract(contents);

}

@Test
public void testCreateContract_UsingPath_ThrowsException() throws HieroException {
when(protocolLayerClient.executeContractCreateTransaction(Mockito.any())).thenThrow(new RuntimeException("Failed"));
HieroException hieroException = assertThrows(HieroException.class, () -> smartContractClient.createContract(path, constructorParams));

assertTrue(hieroException.getMessage().contains("Failed to create contract from path " + path));

}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
package com.openelements.hiero.microprofile;

import com.openelements.hiero.base.AccountClient;
import com.openelements.hiero.base.FileClient;
import com.openelements.hiero.base.FungibleTokenClient;
import com.openelements.hiero.base.HieroContext;
import com.openelements.hiero.base.NftClient;
import com.openelements.hiero.base.SmartContractClient;
import com.openelements.hiero.base.*;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not use * imports

import com.openelements.hiero.base.config.HieroConfig;
import com.openelements.hiero.base.implementation.AccountClientImpl;
import com.openelements.hiero.base.implementation.AccountRepositoryImpl;
Expand Down Expand Up @@ -79,8 +74,8 @@ FileClient createFileClient(@NonNull final ProtocolLayerClient protocolLayerClie
@Produces
@ApplicationScoped
SmartContractClient createSmartContractClient(@NonNull final ProtocolLayerClient protocolLayerClient,
@NonNull final FileClient fileClient) {
return new SmartContractClientImpl(protocolLayerClient, fileClient);
@NonNull final FileClient fileClient, @NonNull IFileReader fileReader) {
return new SmartContractClientImpl(protocolLayerClient, fileClient, fileReader);
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
package com.openelements.hiero.spring.implementation;

import com.openelements.hiero.base.AccountClient;
import com.openelements.hiero.base.FileClient;
import com.openelements.hiero.base.FungibleTokenClient;
import com.openelements.hiero.base.HieroContext;
import com.openelements.hiero.base.NftClient;
import com.openelements.hiero.base.SmartContractClient;
import com.openelements.hiero.base.TopicClient;
import com.openelements.hiero.base.*;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not use * imports

import com.openelements.hiero.base.config.HieroConfig;
import com.openelements.hiero.base.implementation.AccountClientImpl;
import com.openelements.hiero.base.implementation.AccountRepositoryImpl;
Expand Down Expand Up @@ -81,8 +75,8 @@ FileClient fileClient(final ProtocolLayerClient protocolLayerClient) {
}

@Bean
SmartContractClient smartContractClient(final ProtocolLayerClient protocolLayerClient, FileClient fileClient) {
return new SmartContractClientImpl(protocolLayerClient, fileClient);
SmartContractClient smartContractClient(final ProtocolLayerClient protocolLayerClient, FileClient fileClient, IFileReader fileReader) {
return new SmartContractClientImpl(protocolLayerClient, fileClient, fileReader);
}

@Bean
Expand Down